create-yss-spec 3.2.0 → 3.3.1

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 (439) hide show
  1. package/README.md +2 -2
  2. package/package.json +3 -2
  3. package/src/command-runner.mjs +107 -0
  4. package/src/self-update.js +7 -4
  5. package/src/template/instance-runtime.js +1 -1
  6. package/template/.agents/skills/.strategic-design-skills-manifest.json +2 -2
  7. package/template/.agents/skills/code-review/SKILL.md +4 -0
  8. package/template/.agents/skills/code-review/agents/openai.yaml +1 -1
  9. package/template/.agents/skills/code-review/references/yss-review-standards.md +9 -2
  10. package/template/.agents/skills/competitive-intelligence/SKILL.md +4 -4
  11. package/template/.agents/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
  12. package/template/.agents/skills/grill-with-docs/SKILL.md +1 -1
  13. package/template/.agents/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
  14. package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
  15. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
  16. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
  17. package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
  18. package/template/.agents/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
  19. package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
  20. package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
  21. package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
  22. package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
  23. package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
  24. package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
  25. package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
  26. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
  27. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
  28. package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
  29. package/template/.agents/skills/yss-mybatis/SKILL.md +34 -58
  30. package/template/.agents/skills/yss-mybatis/agents/openai.yaml +2 -2
  31. package/template/.agents/skills/yss-mybatis/references/source-index.md +88 -68
  32. package/template/.agents/skills/yss-product-lifecycle/SKILL.md +50 -42
  33. package/template/.agents/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
  34. package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
  35. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
  36. package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +16 -2
  37. package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +5 -2
  38. package/template/.agents/skills/yss-repository/SKILL.md +28 -70
  39. package/template/.agents/skills/yss-repository/agents/openai.yaml +2 -2
  40. package/template/.agents/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
  41. package/template/.agents/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
  42. package/template/.agents/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
  43. package/template/.agents/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
  44. package/template/.agents/skills/yss-research/SKILL.md +1 -1
  45. package/template/.agents/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
  46. package/template/.agents/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
  47. package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
  48. package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
  49. package/template/.agents/skills/yss-stage-decision/SKILL.md +5 -3
  50. package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
  51. package/template/.claude/skills/code-review/SKILL.md +4 -0
  52. package/template/.claude/skills/code-review/agents/openai.yaml +1 -1
  53. package/template/.claude/skills/code-review/references/yss-review-standards.md +9 -2
  54. package/template/.claude/skills/competitive-intelligence/SKILL.md +4 -4
  55. package/template/.claude/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
  56. package/template/.claude/skills/grill-with-docs/SKILL.md +1 -1
  57. package/template/.claude/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
  58. package/template/.claude/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
  59. package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
  60. package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
  61. package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
  62. package/template/.claude/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
  63. package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
  64. package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
  65. package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
  66. package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
  67. package/template/.claude/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
  68. package/template/.claude/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
  69. package/template/.claude/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
  70. package/template/.claude/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
  71. package/template/.claude/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
  72. package/template/.claude/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
  73. package/template/.claude/skills/yss-mybatis/SKILL.md +34 -58
  74. package/template/.claude/skills/yss-mybatis/agents/openai.yaml +2 -2
  75. package/template/.claude/skills/yss-mybatis/references/source-index.md +88 -68
  76. package/template/.claude/skills/yss-product-lifecycle/SKILL.md +50 -42
  77. package/template/.claude/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
  78. package/template/.claude/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
  79. package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
  80. package/template/.claude/skills/yss-product-lifecycle/references/orchestration.md +16 -2
  81. package/template/.claude/skills/yss-product-lifecycle/references/state-model.md +5 -2
  82. package/template/.claude/skills/yss-repository/SKILL.md +28 -70
  83. package/template/.claude/skills/yss-repository/agents/openai.yaml +2 -2
  84. package/template/.claude/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
  85. package/template/.claude/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
  86. package/template/.claude/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
  87. package/template/.claude/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
  88. package/template/.claude/skills/yss-research/SKILL.md +1 -1
  89. package/template/.claude/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
  90. package/template/.claude/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
  91. package/template/.claude/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
  92. package/template/.claude/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
  93. package/template/.claude/skills/yss-stage-decision/SKILL.md +5 -3
  94. package/template/.claude/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
  95. package/template/.codex/skills/code-review/SKILL.md +4 -0
  96. package/template/.codex/skills/code-review/agents/openai.yaml +1 -1
  97. package/template/.codex/skills/code-review/references/yss-review-standards.md +9 -2
  98. package/template/.codex/skills/competitive-intelligence/SKILL.md +4 -4
  99. package/template/.codex/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
  100. package/template/.codex/skills/grill-with-docs/SKILL.md +1 -1
  101. package/template/.codex/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
  102. package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
  103. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
  104. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
  105. package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
  106. package/template/.codex/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
  107. package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
  108. package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
  109. package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
  110. package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
  111. package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
  112. package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
  113. package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
  114. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
  115. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
  116. package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
  117. package/template/.codex/skills/yss-mybatis/SKILL.md +34 -58
  118. package/template/.codex/skills/yss-mybatis/agents/openai.yaml +2 -2
  119. package/template/.codex/skills/yss-mybatis/references/source-index.md +88 -68
  120. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +50 -42
  121. package/template/.codex/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
  122. package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
  123. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
  124. package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +16 -2
  125. package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +5 -2
  126. package/template/.codex/skills/yss-repository/SKILL.md +28 -70
  127. package/template/.codex/skills/yss-repository/agents/openai.yaml +2 -2
  128. package/template/.codex/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
  129. package/template/.codex/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
  130. package/template/.codex/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
  131. package/template/.codex/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
  132. package/template/.codex/skills/yss-research/SKILL.md +1 -1
  133. package/template/.codex/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
  134. package/template/.codex/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
  135. package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
  136. package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
  137. package/template/.codex/skills/yss-stage-decision/SKILL.md +5 -3
  138. package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
  139. package/template/.cursor/skills/code-review/SKILL.md +4 -0
  140. package/template/.cursor/skills/code-review/agents/openai.yaml +1 -1
  141. package/template/.cursor/skills/code-review/references/yss-review-standards.md +9 -2
  142. package/template/.cursor/skills/competitive-intelligence/SKILL.md +4 -4
  143. package/template/.cursor/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
  144. package/template/.cursor/skills/grill-with-docs/SKILL.md +1 -1
  145. package/template/.cursor/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
  146. package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
  147. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
  148. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
  149. package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
  150. package/template/.cursor/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
  151. package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
  152. package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
  153. package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
  154. package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
  155. package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
  156. package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
  157. package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
  158. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
  159. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
  160. package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
  161. package/template/.cursor/skills/yss-mybatis/SKILL.md +34 -58
  162. package/template/.cursor/skills/yss-mybatis/agents/openai.yaml +2 -2
  163. package/template/.cursor/skills/yss-mybatis/references/source-index.md +88 -68
  164. package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +50 -42
  165. package/template/.cursor/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
  166. package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
  167. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
  168. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +16 -2
  169. package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +5 -2
  170. package/template/.cursor/skills/yss-repository/SKILL.md +28 -70
  171. package/template/.cursor/skills/yss-repository/agents/openai.yaml +2 -2
  172. package/template/.cursor/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
  173. package/template/.cursor/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
  174. package/template/.cursor/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
  175. package/template/.cursor/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
  176. package/template/.cursor/skills/yss-research/SKILL.md +1 -1
  177. package/template/.cursor/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
  178. package/template/.cursor/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
  179. package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
  180. package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
  181. package/template/.cursor/skills/yss-stage-decision/SKILL.md +5 -3
  182. package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
  183. package/template/.pi/skills/code-review/SKILL.md +4 -0
  184. package/template/.pi/skills/code-review/agents/openai.yaml +1 -1
  185. package/template/.pi/skills/code-review/references/yss-review-standards.md +9 -2
  186. package/template/.pi/skills/competitive-intelligence/SKILL.md +4 -4
  187. package/template/.pi/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
  188. package/template/.pi/skills/grill-with-docs/SKILL.md +1 -1
  189. package/template/.pi/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
  190. package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
  191. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
  192. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
  193. package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
  194. package/template/.pi/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
  195. package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
  196. package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
  197. package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
  198. package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
  199. package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
  200. package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
  201. package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
  202. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
  203. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
  204. package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
  205. package/template/.pi/skills/yss-mybatis/SKILL.md +34 -58
  206. package/template/.pi/skills/yss-mybatis/agents/openai.yaml +2 -2
  207. package/template/.pi/skills/yss-mybatis/references/source-index.md +88 -68
  208. package/template/.pi/skills/yss-product-lifecycle/SKILL.md +50 -42
  209. package/template/.pi/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
  210. package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
  211. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
  212. package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +16 -2
  213. package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +5 -2
  214. package/template/.pi/skills/yss-repository/SKILL.md +28 -70
  215. package/template/.pi/skills/yss-repository/agents/openai.yaml +2 -2
  216. package/template/.pi/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
  217. package/template/.pi/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
  218. package/template/.pi/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
  219. package/template/.pi/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
  220. package/template/.pi/skills/yss-research/SKILL.md +1 -1
  221. package/template/.pi/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
  222. package/template/.pi/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
  223. package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
  224. package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
  225. package/template/.pi/skills/yss-stage-decision/SKILL.md +5 -3
  226. package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
  227. package/template/.qoder/skills/code-review/SKILL.md +4 -0
  228. package/template/.qoder/skills/code-review/agents/openai.yaml +1 -1
  229. package/template/.qoder/skills/code-review/references/yss-review-standards.md +9 -2
  230. package/template/.qoder/skills/competitive-intelligence/SKILL.md +4 -4
  231. package/template/.qoder/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
  232. package/template/.qoder/skills/grill-with-docs/SKILL.md +1 -1
  233. package/template/.qoder/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
  234. package/template/.qoder/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
  235. package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
  236. package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
  237. package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
  238. package/template/.qoder/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
  239. package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
  240. package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
  241. package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
  242. package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
  243. package/template/.qoder/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
  244. package/template/.qoder/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
  245. package/template/.qoder/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
  246. package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
  247. package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
  248. package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
  249. package/template/.qoder/skills/yss-mybatis/SKILL.md +34 -58
  250. package/template/.qoder/skills/yss-mybatis/agents/openai.yaml +2 -2
  251. package/template/.qoder/skills/yss-mybatis/references/source-index.md +88 -68
  252. package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +50 -42
  253. package/template/.qoder/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
  254. package/template/.qoder/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
  255. package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
  256. package/template/.qoder/skills/yss-product-lifecycle/references/orchestration.md +16 -2
  257. package/template/.qoder/skills/yss-product-lifecycle/references/state-model.md +5 -2
  258. package/template/.qoder/skills/yss-repository/SKILL.md +28 -70
  259. package/template/.qoder/skills/yss-repository/agents/openai.yaml +2 -2
  260. package/template/.qoder/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
  261. package/template/.qoder/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
  262. package/template/.qoder/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
  263. package/template/.qoder/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
  264. package/template/.qoder/skills/yss-research/SKILL.md +1 -1
  265. package/template/.qoder/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
  266. package/template/.qoder/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
  267. package/template/.qoder/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
  268. package/template/.qoder/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
  269. package/template/.qoder/skills/yss-stage-decision/SKILL.md +5 -3
  270. package/template/.qoder/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
  271. package/template/.trae/skills/code-review/SKILL.md +4 -0
  272. package/template/.trae/skills/code-review/agents/openai.yaml +1 -1
  273. package/template/.trae/skills/code-review/references/yss-review-standards.md +9 -2
  274. package/template/.trae/skills/competitive-intelligence/SKILL.md +4 -4
  275. package/template/.trae/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
  276. package/template/.trae/skills/grill-with-docs/SKILL.md +1 -1
  277. package/template/.trae/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
  278. package/template/.trae/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
  279. package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
  280. package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
  281. package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
  282. package/template/.trae/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
  283. package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
  284. package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
  285. package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
  286. package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
  287. package/template/.trae/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
  288. package/template/.trae/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
  289. package/template/.trae/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
  290. package/template/.trae/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
  291. package/template/.trae/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
  292. package/template/.trae/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
  293. package/template/.trae/skills/yss-mybatis/SKILL.md +34 -58
  294. package/template/.trae/skills/yss-mybatis/agents/openai.yaml +2 -2
  295. package/template/.trae/skills/yss-mybatis/references/source-index.md +88 -68
  296. package/template/.trae/skills/yss-product-lifecycle/SKILL.md +50 -42
  297. package/template/.trae/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
  298. package/template/.trae/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
  299. package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
  300. package/template/.trae/skills/yss-product-lifecycle/references/orchestration.md +16 -2
  301. package/template/.trae/skills/yss-product-lifecycle/references/state-model.md +5 -2
  302. package/template/.trae/skills/yss-repository/SKILL.md +28 -70
  303. package/template/.trae/skills/yss-repository/agents/openai.yaml +2 -2
  304. package/template/.trae/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
  305. package/template/.trae/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
  306. package/template/.trae/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
  307. package/template/.trae/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
  308. package/template/.trae/skills/yss-research/SKILL.md +1 -1
  309. package/template/.trae/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
  310. package/template/.trae/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
  311. package/template/.trae/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
  312. package/template/.trae/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
  313. package/template/.trae/skills/yss-stage-decision/SKILL.md +5 -3
  314. package/template/.trae/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
  315. package/template/AGENTS.md +2 -2
  316. package/template/CONTEXT.md +3 -2
  317. package/template/README.md +3 -3
  318. package/template/docs/agents/digital-human-roles.md +1 -1
  319. package/template/docs/agents/digital-human-roles.yaml +13 -11
  320. package/template/docs/agents/issue-tracker.md +1 -1
  321. package/template/docs/agents/strategic-design-skills-integration.md +2 -0
  322. package/template/docs/agents/yss-skill-registry.yaml +5 -0
  323. package/template/docs/architecture/README.md +1 -1
  324. package/template/docs/architecture/templates/business-architecture-template.md +1 -1
  325. package/template/docs/architecture/templates/functional-architecture-template.md +1 -1
  326. package/template/docs/design/README.md +1 -1
  327. package/template/docs/design/templates/interaction-spec-template.md +1 -1
  328. package/template/docs/design/templates/product-overview-design-template.md +1 -1
  329. package/template/docs/{discovery → plan}/IDEATION.md +5 -5
  330. package/template/docs/plan/README.md +9 -0
  331. package/template/docs/plan/entry-review.md +23 -0
  332. package/template/docs/plan/templates/plan-template.md +58 -0
  333. package/template/docs/process/harness-process-tailoring.md +1 -1
  334. package/template/docs/process/lifecycle-artifact-map.md +10 -6
  335. package/template/docs/process/lifecycle-registry-baseline.json +10 -1
  336. package/template/docs/process/lifecycle-registry.yaml +48 -20
  337. package/template/docs/process/plan-migration.md +13 -0
  338. package/template/docs/process/schemas/digital-human-task-package.schema.json +2 -0
  339. package/template/docs/process/schemas/implementation-repository-preparation-result.schema.json +38 -0
  340. package/template/docs/process/schemas/lifecycle-checkpoint.schema.json +3 -0
  341. package/template/docs/process/schemas/lifecycle-registry.schema.json +1 -1
  342. package/template/docs/process/schemas/project-scaffold-contract.schema.json +113 -0
  343. package/template/docs/process/template-engineering-overview.md +2 -2
  344. package/template/docs/process/template-verification-profiles.yaml +25 -0
  345. package/template/docs/process/templates/context-reconciliation-template.yaml +2 -2
  346. package/template/docs/process/templates/lifecycle-checkpoint-template.yaml +1 -1
  347. package/template/docs/requirements/README.md +2 -2
  348. package/template/docs/templates/implementation-repo-registry-template.md +8 -0
  349. package/template/docs/templates/local-parent-ticket-template.md +1 -1
  350. package/template/docs/templates/review-report-template.md +7 -3
  351. package/template/docs/templates/subagent-task-package-template.md +1 -1
  352. package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +1 -1
  353. package/template/scripts/cache-template-commit +2 -2
  354. package/template/scripts/fixtures/strategic-handoff/source-roles.json +7 -7
  355. package/template/scripts/fixtures/user-decision/plan-fixture.mjs +30 -0
  356. package/template/scripts/lib/backend-delivery.mjs +5 -2
  357. package/template/scripts/lib/command-runner.mjs +107 -0
  358. package/template/scripts/lib/context-reconciliation.mjs +34 -0
  359. package/template/scripts/lib/json-schema.mjs +42 -13
  360. package/template/scripts/lib/lifecycle-context-query.mjs +141 -0
  361. package/template/scripts/lib/lifecycle-transition.mjs +118 -6
  362. package/template/scripts/lib/plan-spec-entry.mjs +87 -0
  363. package/template/scripts/lib/scenario-checks.mjs +44 -38
  364. package/template/scripts/lib/skill-registry.mjs +9 -0
  365. package/template/scripts/lib/skill-supply-chain.mjs +18 -2
  366. package/template/scripts/lib/strategic-handoff-io.mjs +5 -4
  367. package/template/scripts/lib/strategic-handoff.mjs +10 -9
  368. package/template/scripts/lib/task-package.mjs +2 -0
  369. package/template/scripts/lib/template-commit-cache.mjs +7 -5
  370. package/template/scripts/query-lifecycle-context +25 -0
  371. package/template/scripts/run-template-verification +9 -3
  372. package/template/scripts/sync-strategic-handoff-tools +9 -0
  373. package/template/scripts/verify-business-language-scenarios +0 -7
  374. package/template/scripts/verify-context-reconciliation +2 -48
  375. package/template/scripts/verify-context-reconciliation-scenarios +1 -1
  376. package/template/scripts/verify-frontend-scaffold-generator-scenarios +2 -0
  377. package/template/scripts/verify-lifecycle-checkpoint +2 -0
  378. package/template/scripts/verify-lifecycle-context-query-scenarios +88 -0
  379. package/template/scripts/verify-lifecycle-transition-scenarios +44 -4
  380. package/template/scripts/verify-plan-spec-entry +11 -0
  381. package/template/scripts/verify-plan-spec-entry-scenarios +79 -0
  382. package/template/scripts/verify-script-performance-scenarios +56 -0
  383. package/template/scripts/verify-subagent-task-package-scenarios +9 -8
  384. package/template/scripts/verify-template-cache-scenarios +11 -1
  385. package/template/scripts/verify-user-decision-scenarios +4 -4
  386. package/template/skills-lock.json +23 -23
  387. package/template.manifest.json +2 -1
  388. package/template.snapshot.json +5 -5
  389. package/template/.agents/skills/yss-mybatis/assets/BaseRepository.java +0 -112
  390. package/template/.agents/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
  391. package/template/.agents/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
  392. package/template/.agents/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
  393. package/template/.agents/skills/yss-mybatis/references/README.md +0 -57
  394. package/template/.agents/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
  395. package/template/.claude/skills/yss-mybatis/assets/BaseRepository.java +0 -112
  396. package/template/.claude/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
  397. package/template/.claude/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
  398. package/template/.claude/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
  399. package/template/.claude/skills/yss-mybatis/references/README.md +0 -57
  400. package/template/.claude/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
  401. package/template/.codex/skills/yss-mybatis/assets/BaseRepository.java +0 -112
  402. package/template/.codex/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
  403. package/template/.codex/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
  404. package/template/.codex/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
  405. package/template/.codex/skills/yss-mybatis/references/README.md +0 -57
  406. package/template/.codex/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
  407. package/template/.cursor/skills/yss-mybatis/assets/BaseRepository.java +0 -112
  408. package/template/.cursor/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
  409. package/template/.cursor/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
  410. package/template/.cursor/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
  411. package/template/.cursor/skills/yss-mybatis/references/README.md +0 -57
  412. package/template/.cursor/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
  413. package/template/.pi/skills/yss-mybatis/assets/BaseRepository.java +0 -112
  414. package/template/.pi/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
  415. package/template/.pi/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
  416. package/template/.pi/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
  417. package/template/.pi/skills/yss-mybatis/references/README.md +0 -57
  418. package/template/.pi/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
  419. package/template/.qoder/skills/yss-mybatis/assets/BaseRepository.java +0 -112
  420. package/template/.qoder/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
  421. package/template/.qoder/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
  422. package/template/.qoder/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
  423. package/template/.qoder/skills/yss-mybatis/references/README.md +0 -57
  424. package/template/.qoder/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
  425. package/template/.trae/skills/yss-mybatis/assets/BaseRepository.java +0 -112
  426. package/template/.trae/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
  427. package/template/.trae/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
  428. package/template/.trae/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
  429. package/template/.trae/skills/yss-mybatis/references/README.md +0 -57
  430. package/template/.trae/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
  431. package/template/docs/discovery/README.md +0 -87
  432. package/template/docs/discovery/reports/.gitkeep +0 -0
  433. package/template/docs/discovery/reports/agent-governance-options.md +0 -71
  434. package/template/docs/discovery/reports/competitor-deep-dive/.gitkeep +0 -0
  435. package/template/docs/discovery/templates/discovery-template.md +0 -94
  436. /package/template/docs/{discovery → plan}/templates/competitive-analysis-template.md +0 -0
  437. /package/template/docs/{discovery → plan}/templates/competitive-matrix-template.md +0 -0
  438. /package/template/docs/{discovery → plan}/templates/market-analysis-template.md +0 -0
  439. /package/template/docs/{discovery → plan}/templates/user-pain-points-template.md +0 -0
@@ -1,5 +1,6 @@
1
1
  import { existsSync, readFileSync, mkdtempSync, rmSync } from "node:fs";
2
2
  import path from "node:path";
3
+ import { buildPlanFixture } from "../fixtures/user-decision/plan-fixture.mjs";
3
4
  import os from "node:os";
4
5
  import { buildDecisionFixture, buildImplementationFixture } from "../fixtures/user-decision/build-fixture.mjs";
5
6
  import { fileURLToPath } from "node:url";
@@ -58,8 +59,8 @@ function validateInvocationBoundary(data) {
58
59
  ensure(native?.default_entry === "yss-product-lifecycle" && native?.formal_artifact_owner === "yss-product-lifecycle", "生命周期原生入口未持有默认正式资产所有权");
59
60
  ensure(native?.user_confirmation_policy_ref === "docs/agents/digital-human-roles.yaml#user_decision_policy", "生命周期人工门禁集合已漂移");
60
61
  const routes = data.work_unit_routes;
61
- ensure(routes?.["work-unit.discovery-requirements"]?.skills?.includes("grilling") && routes?.["work-unit.discovery-requirements"]?.skills?.includes("domain-modeling"), "需求分析工作单元缺少 grilling/domain-modeling");
62
- ensure(routes?.["work-unit.discovery-opportunity"]?.route_by?.market_or_competitor_fact === "competitive-intelligence" && routes["work-unit.discovery-opportunity"].route_by.technical_or_standard_fact === "yss-research:technical-evidence" && routes["work-unit.discovery-opportunity"].route_by.strategy_fact === "yss-research:strategy-evidence", "机会调研事实路由不准确");
62
+ ensure(routes?.["work-unit.plan-requirements"]?.skills?.includes("grilling") && routes?.["work-unit.plan-requirements"]?.skills?.includes("domain-modeling"), "需求分析工作单元缺少 grilling/domain-modeling");
63
+ ensure(routes?.["work-unit.plan-opportunity"]?.route_by?.market_or_competitor_fact === "competitive-intelligence" && routes["work-unit.plan-opportunity"].route_by.technical_or_standard_fact === "yss-research:technical-evidence" && routes["work-unit.plan-opportunity"].route_by.strategy_fact === "yss-research:strategy-evidence", "机会调研事实路由不准确");
63
64
  const strategyResearch = routes?.["work-unit.domain-strategy-design"]?.research_contract;
64
65
  ensure(strategyResearch?.profile === "strategy-evidence" && strategyResearch.mode_before_gate === "evidence-audited" && strategyResearch.artifact_owner === "yss-research" && strategyResearch.downstream_owner === "yss-stage-decision", "领域战略研究合同缺少 profile、门禁前审计或资产所有权边界");
65
66
  const stageDecisionResearch = routes?.["work-unit.stage-decision"]?.research_contract;
@@ -76,7 +77,9 @@ function validateInvocationBoundary(data) {
76
77
  ensure(routes?.["work-unit.frontend-implementation-verification"]?.skills?.includes("code-review") && routes?.["work-unit.frontend-implementation-verification"]?.applies_when === "ui_impact", "前端还原验证未绑定 UI fidelity 审查轴");
77
78
  const reviewRoute = routes?.["work-unit.code-review"];
78
79
  ensure(reviewRoute?.primary_skill === "code-review" && reviewRoute?.review_standards_route?.unique_default_skill === "code-review" && reviewRoute?.review_standards_route?.second_generic_review_skill === "forbidden", "code-review 不是唯一默认审查入口或允许第二套通用审查 skill");
79
- ensure(includesAll(reviewRoute?.supporting_skills, ["alibaba-java-code-style", "yss-ui", "yss-domain"]) && includesAll(reviewRoute?.skills, ["code-review", "alibaba-java-code-style", "yss-ui"]), "审查工作单元缺少 YSS / Alibaba 专项检查输入");
80
+ ensure(includesAll(reviewRoute?.supporting_skills, ["alibaba-java-code-style", "yss-ui", "yss-domain", "yss-repository", "yss-mybatis"]) && includesAll(reviewRoute?.skills, ["code-review", "alibaba-java-code-style", "yss-ui", "yss-repository", "yss-mybatis"]), "审查工作单元缺少 YSS / Alibaba / Repository / MyBatis 专项检查输入");
81
+ const reviewScope = reviewRoute?.review_standards_route?.project_scope;
82
+ ensure(includesAll(reviewScope?.sources, ["candidate-project-root", "implementation-repository-registry", "slice-project-roots", "allowed-write-paths"]) && includesAll(reviewScope?.include, ["project-itself", "registered-backend-development-projects"]) && includesAll(reviewScope?.exclude, ["frontend-projects", "unrelated-submodules", "vendor", "unregistered-directories"]) && reviewScope?.fixed_apps_backend_assumption === "forbidden", "后端审查范围未绑定本体项目与已登记后端研发项目,或仍固定为 apps/backend");
80
83
  const disposition = reviewRoute?.review_standards_route?.finding_disposition;
81
84
  ensure(includesAll(disposition?.same_loop_for, ["product-slice", "template-maintenance"]) && disposition?.reviewer_write_implementation === "forbidden", "审查 finding 闭环未同时覆盖产品切片与模板维护,或允许审查者写实现");
82
85
  ensure(includesAll(disposition?.repair_then_full_rereview?.kinds, ["violation", "machine_check_failure", "blank_applicable_row", "missing_evidence"]) && disposition?.repair_then_full_rereview?.actor === "implementer" && disposition?.repair_then_full_rereview?.then === "recapture_candidate_and_rerun_all_axes", "violation 类 finding 未要求实现者修复后全轴复审");
@@ -92,7 +95,7 @@ function validateInvocationBoundary(data) {
92
95
  }
93
96
  }
94
97
 
95
- function validateWorkflowExecutionResult(payload, contract, workUnitRoutes) {
98
+ function validateWorkflowExecutionResult(payload, contract, workUnitRoutes, options = {}) {
96
99
  for (const field of contract.required) ensure(Object.hasOwn(payload, field), `Workflow Execution Result 缺少 ${field}`);
97
100
  ensure(contract.result_values.includes(payload.result), "Workflow Execution Result result 无效");
98
101
  if (Object.hasOwn(payload, "unavailable_skill")) {
@@ -105,7 +108,7 @@ function validateWorkflowExecutionResult(payload, contract, workUnitRoutes) {
105
108
  const workUnit = workUnitRoutes?.[payload.work_unit];
106
109
  ensure(workUnit, `未知 Workflow Execution Result work_unit: ${payload.work_unit}`);
107
110
  if (payload.result === "completed") {
108
- const routeResult = validateNextRoute(payload.work_unit, payload.next_route, payload);
111
+ const routeResult = validateNextRoute(payload.work_unit, payload.next_route, payload, options);
109
112
  ensure(routeResult.result === "allowed", `Workflow Execution Result next_route 非法: ${routeResult.blocking_signals.join(", ")}`);
110
113
  ensure(payload.context_reconciliation?.status === "reconciled", "project-instance 完成态必须具有 reconciled context_reconciliation");
111
114
  ensure(hasText(payload.context_reconciliation?.ref) && payload.evidence_refs.includes(payload.context_reconciliation.ref) && exists(payload.context_reconciliation.ref), "context_reconciliation.ref 必须可读并包含在 evidence_refs 中");
@@ -125,6 +128,8 @@ function validateWorkflowExecutionResult(payload, contract, workUnitRoutes) {
125
128
  const implementationState = {
126
129
  user_decisions: payload.user_decisions,
127
130
  slice_contract_ref: payload.slice_contract_ref,
131
+ delivery_impacts: payload.delivery_impacts,
132
+ implementation_repository_preparation: payload.implementation_repository_preparation,
128
133
  tracker_kind: payload.tracker_kind,
129
134
  predecessor_work_unit: payload.predecessor_work_unit,
130
135
  ready_for_agent: payload.ready_for_agent,
@@ -164,18 +169,15 @@ function validateInvocationMetadata(boundary, skillContents) {
164
169
  for (const skill of boundary.model_invoked_skills) ensure(!skillContents(skill).includes("disable-model-invocation: true"), `${skill} 不应出现在 model-invoked 白名单`);
165
170
  }
166
171
 
167
- function validateMattProse(skill, adapter) {
168
- ensure(skill.includes("不得写生命周期资产或改变门禁/Ticket 状态") && skill.includes("任何写入前回交本编排器"), "主技能缺少 direct Matt 只导航并回交的说明");
169
- ensure(adapter.includes("仅发现旧路径资产") && adapter.includes("不得调用 `setup-matt-pocock-skills`"), "适配器缺少 setup 旧资产迁移或显式用户入口条件");
170
- ensure(adapter.includes("frontier 为空") && adapter.includes("双方共同理解已确认"), "适配器缺少 grill_exit 的 frontier 或共同理解条件");
171
- ensure(skill.includes("自然语言意向不构成上述结构化 Git 授权") && adapter.includes("本身不是结构化授权"), "主技能或适配器缺少自然语言 Git 意向不是授权的说明");
172
- ensure(adapter.includes("禁止 detached HEAD 提交") && adapter.includes("先推子仓再更新父仓 gitlink"), "适配器缺少 git-submodule 嵌套 Git 授权说明");
173
- }
174
-
175
- function validateInvocationProse(skill, adapter, orchestration) {
176
- ensure(skill.includes("不得自动调用它们或代替其创建正式资产") && skill.includes("Workflow Execution Result"), "主技能未限制 user-invoked 调用或未采用新结果协议");
177
- ensure(adapter.includes("workflow reference 不表示调用") && adapter.includes("正式 Spec、Ticket 或实现资产仍只能由对应显式用户入口创建"), "适配器未限制 workflow reference 的正式资产所有权");
178
- ensure(orchestration.includes("只实际调用允许的 model-invoked skill") && orchestration.includes("用户显式启动"), "编排协议未区分 model-invoked 原语和显式用户入口");
172
+ function validateLifecycleEntrySkill(skill) {
173
+ ensure(/^---\nname: yss-product-lifecycle\n/m.test(skill), "生命周期入口缺少有效 frontmatter");
174
+ ensure(Buffer.byteLength(skill) <= 8192, "生命周期入口超过 8KB 上下文预算");
175
+ for (const reference of ["docs/process/lifecycle-registry.yaml", "references/orchestration-contract.yaml", "docs/agents/yss-skill-registry.yaml", "scripts/query-lifecycle-context"]) {
176
+ ensure(skill.includes(reference), `生命周期入口缺少权威引用: ${reference}`);
177
+ }
178
+ for (const heading of ["### 仓库身份", "### 流转与实现", "### 用户决定", "### 外部副作用与 Git"]) {
179
+ ensure(skill.includes(heading), `生命周期入口缺少边界分组: ${heading}`);
180
+ }
179
181
  }
180
182
 
181
183
  const profiles = {
@@ -192,7 +194,7 @@ const profiles = {
192
194
  prototype: {
193
195
  message: "原型到后端脚手架及后续 YSS 代码生成压力场景验证通过",
194
196
  files: [".agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs", ".agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml"],
195
- markers: [[".agents/skills/yss-product-lifecycle/SKILL.md", "controlled-generation"]]
197
+ markers: [[".agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml", "controlled-generation"]]
196
198
  },
197
199
  implementationContractCompiler: {
198
200
  message: "YSS implementation contract compiler stage 7 scenarios passed",
@@ -248,7 +250,10 @@ export function runScenario(name) {
248
250
  { from: "work-unit.spec-synthesis", to: "work-unit.slice-implementation" },
249
251
  { from: "work-unit.prototype-design", to: "work-unit.slice-implementation" },
250
252
  { from: "work-unit.technical-analysis", to: "work-unit.slice-implementation" },
251
- ]), "生命周期转换图缺少 Spec/原型/技术分析到实现的越级阻断");
253
+ { from: "work-unit.technical-analysis", to: "work-unit.ticket-decomposition" },
254
+ ]), "生命周期转换图缺少工程准备、Ticket 正式化与实现越级阻断");
255
+ ensure(contract.transition_graph?.routes?.["work-unit.implementation-repository-preparation"]?.includes("work-unit.ticket-decomposition"), "实现仓库准备未成为 Ticket 正式化前置");
256
+ ensure(contract.implementation_repository_preparation?.gate === "gate.implementation-repositories-ready", "实现仓库准备聚合门禁缺失");
252
257
  ensure(lifecycleTransitionContract.next_routes["work-unit.ticket-decomposition"]?.includes("work-unit.slice-implementation"), "转换校验器未允许 Ticket 正式化后进入实现");
253
258
  ensure(contract.release_readiness?.conditional?.ui_impact?.includes("gate.frontend-implementation-verified") && contract.frontend_implementation_plan?.acceptance?.includes("no_template_placeholders"), "发布公式或前端计划实质校验不完整");
254
259
  const templateRejected = spawnSync("scripts/verify-frontend-implementation-evidence", ["docs/process/templates/frontend-implementation-plan-template.yaml"], { cwd: root, encoding: "utf8" });
@@ -264,7 +269,9 @@ export function runScenario(name) {
264
269
  process.on("exit", () => rmSync(decisionTemp, { recursive: true, force: true }));
265
270
  const specDecision = buildDecisionFixture(path.join(decisionTemp, "spec"));
266
271
  const implementationDecision = buildImplementationFixture(path.join(decisionTemp, "implementation"), "docs/.scratch/demo/issues/01-valid-slice.md");
272
+ const planFixture = buildPlanFixture(path.join(decisionTemp, 'plan'));
267
273
  const validResult = {
274
+ ...planFixture.state,
268
275
  user_decisions: [specDecision.requirement],
269
276
  result_schema: "workflow-execution-result-v1",
270
277
  work_unit: "work-unit.spec-synthesis",
@@ -275,10 +282,10 @@ export function runScenario(name) {
275
282
  changed_artifacts: [],
276
283
  new_impacts: [],
277
284
  stale_candidates: [],
278
- next_route: "work-unit.ticket-decomposition",
285
+ next_route: "work-unit.implementation-repository-preparation",
279
286
  blocking_signals: []
280
287
  };
281
- validateWorkflowExecutionResult(validResult, data.workflow_execution_result, data.work_unit_routes);
288
+ validateWorkflowExecutionResult(validResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
282
289
  const validTicketResult = {
283
290
  ...validResult,
284
291
  work_unit: "work-unit.ticket-decomposition",
@@ -286,7 +293,7 @@ export function runScenario(name) {
286
293
  ticket_decomposition_result_ref: "docs/.scratch/demo/evidence/ticket-decomposition-result.yaml",
287
294
  vertical_slice_ticket_ref: "docs/.scratch/demo/issues/01-valid-slice.md",
288
295
  };
289
- validateWorkflowExecutionResult(validTicketResult, data.workflow_execution_result, data.work_unit_routes);
296
+ validateWorkflowExecutionResult(validTicketResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
290
297
  const validImplementationResult = {
291
298
  ...validResult,
292
299
  ...implementationDecision.state,
@@ -304,8 +311,16 @@ export function runScenario(name) {
304
311
  slice_contract_status: "approved",
305
312
  slice_contract_persisted: true,
306
313
  slice_contract_current_version: true,
314
+ delivery_impacts: { backend: true, frontend: false },
315
+ implementation_repository_preparation: {
316
+ result: "completed", current_version: true, evidence_refs: ["docs/process/lifecycle-registry.yaml"],
317
+ projects: [
318
+ { project_id: "backend", delivery_role: "backend", status: "existing-and-onboarded", repository_ref: "git://backend", project_root: "/workspace/backend", repository_scope: "external-repository", onboarding_result: { status: "completed", ref: "docs/process/lifecycle-registry.yaml" } },
319
+ { project_id: "frontend-na", delivery_role: "frontend", status: "not-applicable", reason: "no frontend impact" },
320
+ ],
321
+ },
307
322
  };
308
- validateWorkflowExecutionResult(validImplementationResult, data.workflow_execution_result, data.work_unit_routes);
323
+ validateWorkflowExecutionResult(validImplementationResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
309
324
  for (const mutate of [
310
325
  (item) => { item.vertical_slice_ticket_role = "ready-for-human"; },
311
326
  (item) => { item.vertical_slice_ticket_kind = "parent-ticket"; },
@@ -317,22 +332,22 @@ export function runScenario(name) {
317
332
  ]) {
318
333
  const invalid = structuredClone(validImplementationResult); mutate(invalid);
319
334
  let rejected = false;
320
- try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes); } catch { rejected = true; }
335
+ try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root }); } catch { rejected = true; }
321
336
  ensure(rejected, "实现 Workflow Execution Result 的 Ticket 语义变异未被拒绝");
322
337
  }
323
338
  const unavailableResult = structuredClone(validResult);
324
339
  unavailableResult.result = "blocked";
325
340
  unavailableResult.unavailable_skill = { skill: "yss-ui", provider: "codex", fallback: "manual-review", resolution: "needs-human" };
326
341
  unavailableResult.blocking_signals = ["missing_evidence"];
327
- validateWorkflowExecutionResult(unavailableResult, data.workflow_execution_result, data.work_unit_routes);
342
+ validateWorkflowExecutionResult(unavailableResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
328
343
  const malformedUnavailable = structuredClone(unavailableResult);
329
344
  delete malformedUnavailable.unavailable_skill.fallback;
330
345
  let unavailableRejected = false;
331
- try { validateWorkflowExecutionResult(malformedUnavailable, data.workflow_execution_result, data.work_unit_routes); } catch { unavailableRejected = true; }
346
+ try { validateWorkflowExecutionResult(malformedUnavailable, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root }); } catch { unavailableRejected = true; }
332
347
  ensure(unavailableRejected, "技能不可用结果缺少 fallback 时未被拒绝");
333
348
  const compatibleResult = structuredClone(validResult);
334
349
  compatibleResult.workflow_reference = { source: "mattpocock/skills", skill: "to-spec", invocation_mode: "reference" };
335
- validateWorkflowExecutionResult(compatibleResult, data.workflow_execution_result, data.work_unit_routes);
350
+ validateWorkflowExecutionResult(compatibleResult, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root });
336
351
  for (const mutate of [
337
352
  (item) => { delete item.workflow_reference; },
338
353
  (item) => { delete item.context_reconciliation; },
@@ -348,7 +363,7 @@ export function runScenario(name) {
348
363
  ]) {
349
364
  const invalid = structuredClone(validResult); mutate(invalid);
350
365
  let rejected = false;
351
- try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes); } catch { rejected = true; }
366
+ try { validateWorkflowExecutionResult(invalid, data.workflow_execution_result, data.work_unit_routes, { root: planFixture.root }); } catch { rejected = true; }
352
367
  ensure(rejected, "Workflow Execution Result 完成态变异未被拒绝");
353
368
  }
354
369
  let metadataRejected = false;
@@ -377,16 +392,7 @@ export function runScenario(name) {
377
392
  ensure(rejected, "Matt/YSS 契约变异未被 baseline oracle 拒绝");
378
393
  }
379
394
  const skill = read(".agents/skills/yss-product-lifecycle/SKILL.md");
380
- const adapter = read(".agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md");
381
- const orchestration = read(".agents/skills/yss-product-lifecycle/references/orchestration.md");
382
- validateMattProse(skill, adapter);
383
- validateInvocationProse(skill, adapter, orchestration);
384
- let proseRejected = false;
385
- try { validateMattProse(skill.replace("任何写入前回交本编排器", "允许直接写入"), adapter); } catch { proseRejected = true; }
386
- ensure(proseRejected, "Matt/YSS prose 变异未被 baseline oracle 拒绝");
387
- let invocationProseRejected = false;
388
- try { validateInvocationProse(skill.replace("不得自动调用它们或代替其创建正式资产", "可以自动调用并创建正式资产"), adapter, orchestration); } catch { invocationProseRejected = true; }
389
- ensure(invocationProseRejected, "调用边界 prose 变异未被 baseline oracle 拒绝");
395
+ validateLifecycleEntrySkill(skill);
390
396
  for (const relative of ["SKILL.md", "references/matt-yss-adapter.md", "references/orchestration-contract.yaml"]) {
391
397
  ensure(read(`.agents/skills/yss-product-lifecycle/${relative}`) === read(`.codex/skills/yss-product-lifecycle/${relative}`), `YSS 生命周期投影未同步: ${relative}`);
392
398
  }
@@ -166,6 +166,10 @@ function validateReviewInputFinding(reviewInput) {
166
166
  if (reviewInput.completed_requires_no_open_mandatory_violations !== true) fail("未关闭的 mandatory violation 不得 completed");
167
167
  if (reviewInput.completed_requires_no_blank_applicable_rows !== true) fail("适用报告行空白不得 completed");
168
168
  if (reviewInput.reviewer_write_implementation !== "forbidden") fail("review_input 禁止审查者写实现");
169
+ requireObject(reviewInput.scope_resolution, "review_input.scope_resolution");
170
+ requireStringSet(reviewInput.scope_resolution.sources, ["candidate-project-root", "implementation-repository-registry", "slice-project-roots", "allowed-write-paths"], "review_input.scope_resolution.sources");
171
+ requireStringSet(reviewInput.scope_resolution.backend_includes, ["project-itself", "registered-backend-development-projects"], "review_input.scope_resolution.backend_includes");
172
+ requireStringSet(reviewInput.scope_resolution.excludes, ["frontend-projects", "unrelated-submodules", "vendor", "unregistered-directories"], "review_input.scope_resolution.excludes");
169
173
  }
170
174
 
171
175
  function validateCodeReviewRoute(route, resolve) {
@@ -180,6 +184,11 @@ function validateCodeReviewRoute(route, resolve) {
180
184
  if (standards.contract_required_skills !== "required") fail("Standards 必须消费 Slice 合同 required_skills");
181
185
  requireString(standards.report_template, "review_standards_route.report_template");
182
186
  if (!existsSync(path.join(ROOT, standards.report_template))) fail(`审查报告模板不存在: ${standards.report_template}`);
187
+ requireObject(standards.project_scope, "review_standards_route.project_scope");
188
+ requireStringSet(standards.project_scope.sources, ["candidate-project-root", "implementation-repository-registry", "slice-project-roots", "allowed-write-paths"], "review_standards_route.project_scope.sources");
189
+ requireStringSet(standards.project_scope.include, ["project-itself", "registered-backend-development-projects"], "review_standards_route.project_scope.include");
190
+ requireStringSet(standards.project_scope.exclude, ["frontend-projects", "unrelated-submodules", "vendor", "unregistered-directories"], "review_standards_route.project_scope.exclude");
191
+ if (standards.project_scope.fixed_apps_backend_assumption !== "forbidden") fail("code-review 不得把后端审查范围固定为 apps/backend");
183
192
  const conditional = standards.conditional_skills;
184
193
  if (!conditional || typeof conditional !== "object" || Array.isArray(conditional)) {
185
194
  fail("review_standards_route.conditional_skills 必须是对象");
@@ -117,7 +117,16 @@ function loadStrategicDesignSkillManifest() {
117
117
  return validateStrategicDesignSkillManifest(JSON.parse(readFileSync(STRATEGIC_DESIGN_MANIFEST_PATH, "utf8")));
118
118
  }
119
119
  function git(args) { return spawnSync("git", args, { cwd: ROOT, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }); }
120
- function tracked(relativePath) { return git(["ls-files", "-z", "--", relativePath]).stdout.length > 0; }
120
+ function trackedPaths() {
121
+ const result = git(["ls-files", "-z"]);
122
+ if (result.status !== 0) throw new TypeError("无法读取 Git 受跟踪路径");
123
+ const paths = new Set();
124
+ for (const file of result.stdout.split("\0").filter(Boolean)) {
125
+ let ref = file;
126
+ while (ref !== ".") { paths.add(ref); ref = path.posix.dirname(ref); }
127
+ }
128
+ return paths;
129
+ }
121
130
  function parseLock() { return existsSync(LOCK_PATH) ? JSON.parse(readFileSync(LOCK_PATH, "utf8")) : null; }
122
131
  function sharedFromLock(lock) {
123
132
  const shared = lock?.version === 3 && lock.skills?.shared;
@@ -137,6 +146,13 @@ export function unlockedCanonicalEntries(names, allowedNames, hasSkillMd = () =>
137
146
  return names.filter((name) => !allowed.has(name) && !OBSOLETE.has(name) && hasSkillMd(name)).sort();
138
147
  }
139
148
  export function syncSkills({ check = false } = {}) {
149
+ let trackedSet;
150
+ const tracked = ref => (trackedSet ??= trackedPaths()).has(ref);
151
+ const sourceHashes = new Map();
152
+ const sourceHash = source => {
153
+ if (!sourceHashes.has(source)) sourceHashes.set(source, treeHash(source));
154
+ return sourceHashes.get(source);
155
+ };
140
156
  const lock = parseLock();
141
157
  const shared = sharedFromLock(lock);
142
158
  const absent = shared.filter((name) => !lstatSafe(path.join(SOURCE_ROOT, name))?.isDirectory());
@@ -162,7 +178,7 @@ export function syncSkills({ check = false } = {}) {
162
178
  if (info?.isSymbolicLink()) {
163
179
  if (!existsSync(target) || realpathSync(target) !== realpathSync(source)) drift.push(`projection target mismatch: ${relative(target)}`);
164
180
  } else if (!info?.isDirectory()) drift.push(`missing projection: ${relative(target)}`);
165
- else if (treeHash(source) !== treeHash(target)) drift.push(`projection drift: ${relative(target)}`);
181
+ else if (sourceHash(source) !== treeHash(target)) drift.push(`projection drift: ${relative(target)}`);
166
182
  } else if (info?.isSymbolicLink() && existsSync(target) && realpathSync(target) === realpathSync(source)) {
167
183
  continue;
168
184
  } else {
@@ -3,6 +3,7 @@ import { existsSync, lstatSync, readdirSync, readFileSync, mkdirSync, writeFileS
3
3
  import path from 'node:path';
4
4
  import { spawnSync } from 'node:child_process';
5
5
  import { fileURLToPath } from 'node:url';
6
+ import { validateJsonSchemas } from './json-schema.mjs';
6
7
  import { parseDocument } from '../vendor/yaml.mjs';
7
8
  export const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
8
9
  export const ensure = (condition, message) => { if (!condition) throw new TypeError(message); };
@@ -50,11 +51,11 @@ export function project(root) {
50
51
  ensure(value.schema_version === 1 && value.repository_mode === 'project-instance', '只允许 project-instance 导出或导入业务包');
51
52
  return realpathSync(root);
52
53
  }
53
- export function schema(value, ref) {
54
- const program = 'import json,sys; from jsonschema import Draft202012Validator; s=json.load(open(sys.argv[1])); v=json.load(sys.stdin); errors=list(Draft202012Validator(s).iter_errors(v)); print("\\n".join(str(e) for e in errors)); sys.exit(bool(errors))';
55
- const out = spawnSync('python3', ['-c', program, safe(ROOT, ref)], { input: JSON.stringify(value), encoding: 'utf8', maxBuffer: 4 * 1024 * 1024 });
56
- ensure(out.status === 0, `schema 校验失败: ${out.error?.message || out.stdout || out.stderr}`);
54
+ export function schemaBatch(items) {
55
+ const results = validateJsonSchemas(items.map(([value, ref]) => ({ value, schemaPath: safe(ROOT, ref), formatChecker: false, errorStyle: 'verbose' })));
56
+ for (const result of results) ensure(result.valid, `schema 校验失败: ${result.error}\n`);
57
57
  }
58
+ export function schema(value, ref) { schemaBatch([[value, ref]]); }
58
59
  export function archive(command, source, destination) {
59
60
  const out = spawnSync('python3', [path.join(ROOT, 'scripts/lib/strategic-handoff-zip.py'), command, source, destination], { encoding: 'utf8' });
60
61
  ensure(out.status === 0, `ZIP 操作失败: ${out.error?.message || out.stderr}`);
@@ -1,7 +1,7 @@
1
1
  import { existsSync, lstatSync, readFileSync, mkdirSync, mkdtempSync, renameSync, rmSync, cpSync } from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { tmpdir } from 'node:os';
4
- import { ensure, canonical, digest, hash, json, parse, read, safe, relative, files, write, project, schema, archive, ROOT, sourceApprovalPolicy } from './strategic-handoff-io.mjs';
4
+ import { ensure, canonical, digest, hash, json, parse, read, safe, relative, files, write, project, schema, schemaBatch, archive, ROOT, sourceApprovalPolicy } from './strategic-handoff-io.mjs';
5
5
  import { parseContextSource, parseContextContract, resolveContextTermRefs } from './context-contract.mjs';
6
6
  import { countersignRuleForGate } from './digital-human-roles.mjs';
7
7
  import { validateApprovalRecord } from './approval-record.mjs';
@@ -91,8 +91,7 @@ export async function inspectSource(root, handoffRef) {
91
91
  snapshot(handoff.source_context_snapshot,source); checkDelta(handoff,source);
92
92
  const strategy=read(safe(root,handoff.source.domain_strategy_ref.persisted_ref));
93
93
  const stage=read(safe(root,handoff.source.stage_decision_package_ref.persisted_ref));
94
- schema(strategy,'docs/process/schemas/strategic-handoff-domain-strategy.schema.json');
95
- schema(stage,'docs/process/schemas/strategic-handoff-stage-decision-package.schema.json');
94
+ schemaBatch([[strategy,'docs/process/schemas/strategic-handoff-domain-strategy.schema.json'],[stage,'docs/process/schemas/strategic-handoff-stage-decision-package.schema.json']]);
96
95
  snapshot(strategy.context_snapshot,source); snapshot(stage.context_snapshot,source);
97
96
  ensure(strategy.status==='approved' && stage.status==='approved', '战略合同/方案决策包尚未批准');
98
97
  ensure(strategy.domain_strategy_id===handoff.source.domain_strategy_ref.id && strategy.domain_version===handoff.source.domain_strategy_ref.version, '战略身份/版本不一致');
@@ -141,21 +140,22 @@ function collect(root, handoffRef, handoff, config) {
141
140
  if(Array.isArray(value)) { if(key==='evidence_refs') value.forEach(enqueue); else value.forEach(v=>refs(v,key)); }
142
141
  else if(value && typeof value==='object') for(const [k,v]of Object.entries(value)) { if(['approval_ref','persisted_ref','user_decision_ref'].includes(k)&&typeof v==='string')enqueue(v); else if(k==='ref'&&typeof v==='string'&&!/^[a-z]+:\/\//i.test(v))enqueue(v); else refs(v,k); }
143
142
  }
143
+ let totalBytes = 0;
144
144
  while(queue.length) {
145
145
  const ref=symbolic[queue[0]]||queue[0]; queue.shift(); if(/^https?:\/\//i.test(ref))continue; relative(ref);
146
146
  if(collected.has(ref))continue;
147
147
  const full=safe(root,ref),stat=lstatSync(full);
148
148
  if(stat.isDirectory()) { queue.push(...files(root,ref)); continue; }
149
149
  ensure(stat.isFile() && stat.size<=MAX_BYTES,`源文件类型/大小无效: ${ref}`);
150
- const bytes=readFileSync(full); collected.set(ref,bytes);
151
- ensure(collected.size<=20000 && [...collected.values()].reduce((n,b)=>n+b.length,0)<=MAX_BYTES,'交接包大小超限');
150
+ const bytes=readFileSync(full); collected.set(ref,bytes); totalBytes += bytes.length;
151
+ ensure(collected.size<=20000 && totalBytes<=MAX_BYTES,'交接包大小超限');
152
152
  if(/\.(yaml|yml|json)$/.test(ref))refs(parse(bytes));
153
153
  queue.push(...documentLinks(ref,bytes));
154
154
  }
155
155
  return collected;
156
156
  }
157
- function materialize(bundleRoot, manifest, destination) {
158
- for(const file of manifest.files.filter(x=>x.original_ref))write(destination,file.original_ref,readFileSync(safe(bundleRoot,file.path)));
157
+ function materialize(captured, manifest, destination) {
158
+ for(const file of manifest.files.filter(x=>x.original_ref))write(destination,file.original_ref,captured.get(file.path));
159
159
  }
160
160
  export async function openBundle(input, action) {
161
161
  const temp=mkdtempSync(path.join(tmpdir(),'yss-handoff-'));
@@ -170,10 +170,11 @@ export async function openBundle(input, action) {
170
170
  ensure(new Set(paths.map(x=>x.toLowerCase())).size===paths.length,'包文件路径重复');
171
171
  ensure(own([...paths,'manifest.json'].sort(),files(root).sort()),'包文件缺失或存在未登记文件');
172
172
  ensure(manifest.files.length<=20000 && manifest.files.reduce((n,f)=>n+f.size_bytes,0)<=MAX_BYTES,'包大小超限');
173
- for(const file of manifest.files){const bytes=readFileSync(safe(root,file.path));ensure(bytes.length===file.size_bytes && hash(bytes)===file.sha256,`文件摘要不一致: ${file.path}`);if(file.original_ref)relative(file.original_ref);}
173
+ const captured = new Map();
174
+ for(const file of manifest.files){const bytes=readFileSync(safe(root,file.path));ensure(bytes.length===file.size_bytes && hash(bytes)===file.sha256,`文件摘要不一致: ${file.path}`);if(file.original_ref)relative(file.original_ref);captured.set(file.path,bytes);}
174
175
  const originals=manifest.files.filter(x=>x.original_ref).map(x=>x.original_ref);
175
176
  ensure(new Set(originals.map(x=>x.toLowerCase())).size===originals.length,'源路径重复');
176
- const source=path.join(temp,'source');mkdirSync(source);materialize(root,manifest,source);
177
+ const source=path.join(temp,'source');mkdirSync(source);materialize(captured,manifest,source);
177
178
  const inspected=await inspectSource(source,manifest.handoff_ref);
178
179
  ensure(manifest.bundle_id===inspected.handoff.handoff_id && manifest.version===inspected.handoff.handoff_version,'包身份与源交接不一致');
179
180
  ensure(own(read(safe(root,'indexes/rules.json')),inspected.indexes.rules) && own(read(safe(root,'indexes/scenarios.json')),inspected.indexes.scenarios),'规则/场景索引与源资产不一致');
@@ -6,6 +6,7 @@ import { loadRegistry, ROOT } from "./lifecycle-registry.mjs";
6
6
  import { loadMaintenanceCheckpoint, validateMaintenanceCheckpoint } from "./maintenance-intensity.mjs";
7
7
  import { assertImplementationDecision } from "./user-decision.mjs";
8
8
  import { validateNextRoute } from "./lifecycle-transition.mjs";
9
+ import { assertPlanSpecEntry } from "./plan-spec-entry.mjs";
9
10
  import { enforceHarnessTaskScope } from "./harness-execution-scope.mjs";
10
11
  import { enforceFrontendDelivery } from "./frontend-delivery-boundary.mjs";
11
12
  import { LEGACY_TASK_PACKAGE_SCHEMA, TASK_PACKAGE_SCHEMA, validateTaskPackageSchema } from "./task-package-schema.mjs";
@@ -59,6 +60,7 @@ function validateSkillSource(value, registry) {
59
60
  }
60
61
 
61
62
  function validateCommon(value, registry, lifecycle) {
63
+ if (value.work_unit_id === 'work-unit.spec-synthesis') assertPlanSpecEntry(value);
62
64
  const workUnit = lifecycle.work_units.find((item) => item.id === value.work_unit_id);
63
65
  if (!workUnit && value.contract.kind !== "slice-implementation") fail(`未知 work_unit_id: ${value.work_unit_id}`);
64
66
  const roleDefaults = taskPackageDefaults(value.role_id, registry);
@@ -1,3 +1,4 @@
1
+ import { runCommandSync } from "./command-runner.mjs";
1
2
  import { spawnSync } from "node:child_process";
2
3
  import { createHash } from "node:crypto";
3
4
  import { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
@@ -7,13 +8,14 @@ import { ROOT } from "./template-verification.mjs";
7
8
 
8
9
  function fail(message) { throw new TypeError(message); }
9
10
  function ensure(condition, message) { if (!condition) fail(message); }
10
- function git(args, cwd) {
11
- const result = spawnSync("git", args, { cwd, encoding: "utf8" });
12
- if (result.status !== 0) fail(result.stderr.trim() || `git ${args.join(" ")} 执行失败`);
11
+ function git(args, cwd, timeoutMs = 0, cleanupPathsOnFailure = []) {
12
+ const result = args.includes("fetch") ? runCommandSync("git", args, { cwd, timeoutMs, progress: true, cleanupPathsOnFailure }) : spawnSync("git", args, { cwd, encoding: "utf8" });
13
+ if (result.status !== 0) fail(result.termination || result.error?.message || result.stderr.trim() || `git ${args.join(" ")} 执行失败`);
13
14
  return result.stdout.trim();
14
15
  }
15
16
 
16
- export function acquireTemplateCommit({ repository, commit, cacheRoot = path.join(ROOT, ".template-source/cache/remote-templates"), allowLocal = false }) {
17
+ export function acquireTemplateCommit({ repository, commit, cacheRoot = path.join(ROOT, ".template-source/cache/remote-templates"), allowLocal = false, timeoutMs = 0 }) {
18
+ ensure(Number.isFinite(timeoutMs) && timeoutMs >= 0, "timeoutMs 必须是非负毫秒数");
17
19
  ensure(typeof repository === "string" && repository.trim(), "repository 不能为空");
18
20
  ensure(/^[a-f0-9]{40}$/.test(commit), "模板 ref 必须是 40 位 commit");
19
21
  if (!allowLocal) ensure(/^(?:https?:\/\/|ssh:\/\/|git@)/.test(repository), "正式模板缓存只接受远程 repository URL");
@@ -35,7 +37,7 @@ export function acquireTemplateCommit({ repository, commit, cacheRoot = path.joi
35
37
  try {
36
38
  const temporaryRepository = path.join(temporary, "repository.git");
37
39
  git(["init", "--bare", "-q", temporaryRepository], ROOT);
38
- git(["--git-dir", temporaryRepository, "fetch", "--depth=1", "--no-tags", repository, commit], ROOT);
40
+ git(["--git-dir", temporaryRepository, "fetch", "--depth=1", "--no-tags", repository, commit], ROOT, timeoutMs, [temporary]);
39
41
  const actual = git(["--git-dir", temporaryRepository, "rev-parse", "FETCH_HEAD^{commit}"], ROOT);
40
42
  ensure(actual === commit, `远程返回 commit 与请求不一致: ${actual}`);
41
43
  writeFileSync(path.join(temporary, "metadata.json"), `${JSON.stringify({ schema_version: 1, key, repository, commit })}\n`);
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { queryLifecycleContext } from "./lib/lifecycle-context-query.mjs";
4
+
5
+ try {
6
+ const { values } = parseArgs({
7
+ options: {
8
+ mode: { type: "string" },
9
+ stage: { type: "string" },
10
+ "work-unit": { type: "string" },
11
+ include: { type: "string", multiple: true },
12
+ },
13
+ strict: true,
14
+ });
15
+ const result = queryLifecycleContext({
16
+ mode: values.mode,
17
+ stageId: values.stage,
18
+ workUnitId: values["work-unit"],
19
+ include: values.include ?? [],
20
+ });
21
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
22
+ } catch (error) {
23
+ process.stderr.write(`${error.message}\n`);
24
+ process.exitCode = 1;
25
+ }
@@ -23,12 +23,18 @@ function collectChangedFiles(base) {
23
23
  function runCommand(command) {
24
24
  return new Promise((resolve) => {
25
25
  const started = Date.now();
26
+ process.stderr.write(`[开始] ${command}\n`);
26
27
  const child = spawn(command, { cwd: ROOT, shell: true, env: process.env, stdio: ["ignore", "pipe", "pipe"] });
27
28
  let stdout = "";
28
29
  let stderr = "";
29
30
  child.stdout.on("data", (chunk) => { stdout += chunk; });
30
31
  child.stderr.on("data", (chunk) => { stderr += chunk; });
31
- child.on("close", (code) => resolve({ command, code: code ?? 1, duration_ms: Date.now() - started, stdout, stderr }));
32
+ child.on("error", error => { stderr += `${error.message}\n`; });
33
+ child.on("close", (code) => {
34
+ const duration_ms = Date.now() - started;
35
+ process.stderr.write(`[${code === 0 ? "完成" : "失败"}] ${command} (${duration_ms}ms, exit=${code ?? 1})\n`);
36
+ resolve({ command, code: code ?? 1, duration_ms, stdout, stderr });
37
+ });
32
38
  });
33
39
  }
34
40
 
@@ -106,8 +112,8 @@ try {
106
112
  const concurrency = Number(values.concurrency || plan.max_concurrency);
107
113
  if (!Number.isInteger(concurrency) || concurrency < 1 || concurrency > 4) throw new TypeError("concurrency 必须为 1..4");
108
114
 
109
- process.stdout.write(`模板核验 profile: ${plan.requested_profile} -> ${plan.effective_profile}\n`);
110
- if (plan.escalation_reason) process.stdout.write(`自动升级原因: ${plan.escalation_reason}\n`);
115
+ process.stderr.write(`模板核验 profile: ${plan.requested_profile} -> ${plan.effective_profile}\n`);
116
+ if (plan.escalation_reason) process.stderr.write(`自动升级原因: ${plan.escalation_reason}\n`);
111
117
  const groups = await runGroups(plan, modeResult.stdout.trim(), concurrency);
112
118
  printResults(groups);
113
119
  const failed = groups.flatMap((group) => group.results).find((result) => result.code !== 0);
@@ -7,10 +7,19 @@ const root=path.resolve(import.meta.dirname,'..');
7
7
  const check=process.argv.includes('--check');
8
8
  const targets=['submodules/yss-harness-design-agent','submodules/yss-harness-dev-agent','submodules/yss-harness-backend-agent','submodules/yss-harness-frontend-agent'];
9
9
  const shared=['scripts/strategic-handoff','scripts/verify-strategic-handoff-consumption','scripts/verify-strategic-handoff-package-scenarios','scripts/verify-strategic-context-import','scripts/verify-strategic-context-import-scenarios','scripts/lib/context-contract.mjs','docs/process/strategic-handoff-package.md','docs/process/schemas/strategic-design-handoff.schema.json',...readdirSync(path.join(root,'scripts/lib')).filter(x=>x.startsWith('strategic-handoff-')||x==='strategic-handoff.mjs').map(x=>`scripts/lib/${x}`),...readdirSync(path.join(root,'docs/process/schemas')).filter(x=>x.startsWith('strategic-handoff-')).map(x=>`docs/process/schemas/${x}`),...readdirSync(path.join(root,'scripts/fixtures/strategic-handoff')).map(x=>`scripts/fixtures/strategic-handoff/${x}`)];
10
+ shared.push('scripts/lib/command-runner.mjs','scripts/lib/json-schema.mjs','scripts/lib/context-reconciliation.mjs','scripts/verify-context-reconciliation');
10
11
  shared.push('scripts/instantiate-harness','scripts/backend-delivery','scripts/verify-frontend-delivery','scripts/lib/backend-delivery.mjs','scripts/lib/frontend-delivery.mjs','scripts/lib/frontend-delivery-boundary.mjs','docs/process/frontend-backend-delivery.md','docs/process/schemas/backend-delivery.schema.json','docs/process/schemas/backend-delivery-verification.schema.json','docs/process/schemas/frontend-delivery-acceptance.schema.json');
11
12
  let differences=[];
12
13
  // 专职执行范围由各模板持有;后端只消费 wire 校验器,不恢复原型构建技能。
13
14
  function sync(source,dest){let bytes=readFileSync(source);if(dest.includes('/yss-harness-backend-agent/')){let content=bytes.toString();if(dest.endsWith('/scripts/lib/strategic-handoff.mjs'))content=content.replace('../../.agents/skills/yss-prototype-stage/scripts/visual-baseline-contract.mjs','./visual-baseline-contract.mjs');if(dest.endsWith('/scripts/fixtures/strategic-handoff/fixture.mjs'))content=content.replace('../../../.agents/skills/yss-prototype-stage/scripts/visual-baseline-contract.mjs','../../lib/visual-baseline-contract.mjs');bytes=Buffer.from(content);}if(!existsSync(dest)||!bytes.equals(readFileSync(dest))){differences.push(path.relative(root,dest));if(!check){mkdirSync(path.dirname(dest),{recursive:true});writeFileSync(dest,bytes);}}if(!check&&path.basename(path.dirname(dest))==='scripts'&&!path.extname(dest))chmodSync(dest,0o755);}
15
+ // CLI core owns the portable external-command runner; all runtime copies are generated here.
16
+ sync(path.join(root,'.template-source/cli-core/command-runner.mjs'),path.join(root,'scripts/lib/command-runner.mjs'));
17
+ for(const name of ['create-yss-spec','create-yss-strategic-design','create-yss-harness-dev']) {
18
+ const target=`submodules/${name}`;
19
+ if(!existsSync(path.join(root,target,'.git')))continue;
20
+ if(!check){const state=inspectWorkingTreeScope(root,{project_root:target,repository_scope:'git-submodule',checkout_state:'attached-branch'});if(!state.writable)throw new Error(`${target}: ${state.violation}`);}
21
+ sync(path.join(root,'.template-source/cli-core/command-runner.mjs'),path.join(root,target,'src/command-runner.mjs'));
22
+ }
14
23
  for(const kind of ['domain-strategy','stage-decision-package'])sync(path.join(root,`.agents/skills/yss-stage-decision/references/${kind}.schema.json`),path.join(root,`docs/process/schemas/strategic-handoff-${kind}.schema.json`));
15
24
  for(const target of targets){
16
25
  if(!existsSync(path.join(root,target,'.git')))continue;
@@ -25,13 +25,6 @@ for (const relativePath of PUBLIC_FILES) {
25
25
  }
26
26
  }
27
27
 
28
- const lifecycle = read(".agents/skills/yss-product-lifecycle/SKILL.md");
29
- for (const phrase of [
30
- "机会与目标 → 业务故事 → 责任与交接 → 规则、例子与疑问 → 可验收需求 → 页面验证 → 业务任务 → 交接研发",
31
- "业务方案总览",
32
- "不成为新的事实源",
33
- ]) assert.match(lifecycle, new RegExp(phrase));
34
-
35
28
  const registry = read("docs/process/lifecycle-registry.yaml");
36
29
  for (const stableId of ["work-unit.domain-strategy-design", "artifact.domain-strategy", "gate.domain-strategy-approved"]) {
37
30
  assert.match(registry, new RegExp(`id: ${stableId.replaceAll(".", "\\.")}`));
@@ -1,56 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { existsSync, readFileSync } from "node:fs";
3
- import path from "node:path";
4
- import { spawnSync } from "node:child_process";
5
2
  import { parseArgs } from "node:util";
6
- import { fileURLToPath } from "node:url";
7
- import { parseDocument } from "./vendor/yaml.mjs";
8
- import { resolveContextTermRefs, verifyContextSnapshot } from "./lib/context-contract.mjs";
9
-
10
- const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
11
- const schemaPath = path.join(repoRoot, "docs/process/schemas/context-reconciliation.schema.json");
12
- const pythonValidator = String.raw`
13
- import json, sys
14
- from jsonschema import Draft202012Validator
15
- schema = json.load(open(sys.argv[1], encoding="utf-8"))
16
- value = json.load(sys.stdin)
17
- errors = sorted(Draft202012Validator(schema).iter_errors(value), key=lambda error: list(error.absolute_path))
18
- for error in errors:
19
- where = ".".join(str(part) for part in error.absolute_path) or "<root>"
20
- print(f"{where}: {error.message}", file=sys.stderr)
21
- sys.exit(1 if errors else 0)
22
- `;
23
-
24
- function parseFile(file) {
25
- const document = parseDocument(readFileSync(file, "utf8"), { maxAliasCount: 0, uniqueKeys: true });
26
- if (document.errors.length) throw new TypeError(document.errors[0].message);
27
- return document.toJS({ maxAliasCount: 0 });
28
- }
29
-
3
+ import { verifyContextReconciliation } from "./lib/context-reconciliation.mjs";
30
4
  try {
31
5
  const { values, positionals } = parseArgs({ options: { root: { type: "string", default: process.cwd() } }, allowPositionals: true, strict: true });
32
6
  if (positionals.length !== 1) throw new TypeError("用法: scripts/verify-context-reconciliation [--root <repo>] <record.yaml|json>");
33
- const root = path.resolve(values.root);
34
- const file = path.resolve(positionals[0]);
35
- const value = parseFile(file);
36
- const schemaResult = spawnSync("python3", ["-c", pythonValidator, schemaPath], { encoding: "utf8", input: JSON.stringify(value) });
37
- if (schemaResult.status !== 0) throw new TypeError(`${schemaResult.stdout}${schemaResult.stderr}`.trim());
38
- const manifest = parseFile(path.join(root, "yss-project.yaml"));
39
- if (value.repository_mode !== manifest.repository_mode) throw new TypeError("repository_mode 必须与根目录 yss-project.yaml 一致");
40
- const contract = verifyContextSnapshot(value.context_snapshot, { root });
41
- const changedRefs = [...value.changes.added, ...value.changes.updated, ...value.changes.deprecated];
42
- resolveContextTermRefs(contract, changedRefs);
43
- if (new Set(changedRefs).size !== changedRefs.length) throw new TypeError("changes 中的术语引用不得跨分类重复");
44
- if (value.repository_mode === "project-instance" && value.status !== "reconciled") throw new TypeError("project-instance 工作单元只有 status=reconciled 才允许批准或进入下一步");
45
- if (value.status === "reconciled" && value.unresolved_terms.length) throw new TypeError("reconciled 不得包含 unresolved_terms");
46
- if (value.status === "blocked" && value.unresolved_terms.length === 0) throw new TypeError("blocked 必须说明 unresolved_terms");
47
- if (value.status === "not-applicable" && (value.repository_mode !== "template-source" || !value.reason)) throw new TypeError("not-applicable 只适用于 template-source 且必须说明 reason");
48
- for (const ref of value.evidence_refs) {
49
- if (/^https?:\/\//.test(ref)) continue;
50
- const resolved = path.resolve(root, ref);
51
- if (!resolved.startsWith(`${root}${path.sep}`) && resolved !== root) throw new TypeError(`evidence_ref 越出仓库: ${ref}`);
52
- if (!existsSync(resolved)) throw new TypeError(`evidence_ref 不可读: ${ref}`);
53
- }
7
+ verifyContextReconciliation(positionals[0], { root: values.root });
54
8
  process.stdout.write("Context reconciliation 验证通过\n");
55
9
  } catch (error) {
56
10
  process.stderr.write(`Context reconciliation 验证失败: ${error.message}\n`);
@@ -40,7 +40,7 @@ function record(overrides = {}) {
40
40
  return {
41
41
  schema_version: 1,
42
42
  repository_mode: "project-instance",
43
- stage: "stage.discovery",
43
+ stage: "stage.plan",
44
44
  work_unit: "work-unit.domain-strategy-design",
45
45
  status: "reconciled",
46
46
  context_snapshot: snapshot,
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../.agents/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs";
@@ -6,6 +6,7 @@ import { parseArgs } from "node:util";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { parseDocument } from "./vendor/yaml.mjs";
8
8
  import { assertCheckpointApprovals, assertCheckpointUserDecisions } from "./lib/approval-record.mjs";
9
+ import { assertPlanCheckpoint } from "./lib/plan-spec-entry.mjs";
9
10
 
10
11
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
11
12
  const schemaPath = path.join(root, "docs/process/schemas/lifecycle-checkpoint.schema.json");
@@ -32,6 +33,7 @@ try {
32
33
  const result = spawnSync("python3", ["-c", validator, schemaPath], { cwd: root, encoding: "utf8", input: JSON.stringify(value) });
33
34
  if (result.status !== 0) throw new TypeError(`${result.stdout}${result.stderr}`.trim());
34
35
  assertCheckpointApprovals(value, sourcePath);
36
+ assertPlanCheckpoint(value);
35
37
  assertCheckpointUserDecisions(value);
36
38
  if (value.repository_mode === "project-instance" && ["paused-human-gate", "completed"].includes(value.status)) {
37
39
  if (value.context_reconciliation?.status !== "reconciled" || !value.context_reconciliation?.ref) throw new TypeError("project-instance 在会签或完成前必须具有 reconciled context_reconciliation");