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.
- package/README.md +2 -2
- package/package.json +3 -2
- package/src/command-runner.mjs +107 -0
- package/src/self-update.js +7 -4
- package/src/template/instance-runtime.js +1 -1
- package/template/.agents/skills/.strategic-design-skills-manifest.json +2 -2
- package/template/.agents/skills/code-review/SKILL.md +4 -0
- package/template/.agents/skills/code-review/agents/openai.yaml +1 -1
- package/template/.agents/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.agents/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.agents/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.agents/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.agents/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.agents/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.agents/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.agents/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.agents/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.agents/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.agents/skills/yss-repository/SKILL.md +28 -70
- package/template/.agents/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.agents/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.agents/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.agents/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.agents/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.agents/skills/yss-research/SKILL.md +1 -1
- package/template/.agents/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.agents/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.agents/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.agents/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.claude/skills/code-review/SKILL.md +4 -0
- package/template/.claude/skills/code-review/agents/openai.yaml +1 -1
- package/template/.claude/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.claude/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.claude/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.claude/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.claude/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.claude/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.claude/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.claude/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.claude/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.claude/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.claude/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.claude/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.claude/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.claude/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.claude/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.claude/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.claude/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.claude/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.claude/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.claude/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.claude/skills/yss-repository/SKILL.md +28 -70
- package/template/.claude/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.claude/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.claude/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.claude/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.claude/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.claude/skills/yss-research/SKILL.md +1 -1
- package/template/.claude/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.claude/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.claude/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.claude/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.claude/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.claude/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.codex/skills/code-review/SKILL.md +4 -0
- package/template/.codex/skills/code-review/agents/openai.yaml +1 -1
- package/template/.codex/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.codex/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.codex/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.codex/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.codex/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.codex/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.codex/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.codex/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.codex/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.codex/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.codex/skills/yss-repository/SKILL.md +28 -70
- package/template/.codex/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.codex/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.codex/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.codex/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.codex/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.codex/skills/yss-research/SKILL.md +1 -1
- package/template/.codex/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.codex/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.codex/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.codex/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.cursor/skills/code-review/SKILL.md +4 -0
- package/template/.cursor/skills/code-review/agents/openai.yaml +1 -1
- package/template/.cursor/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.cursor/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.cursor/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.cursor/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.cursor/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.cursor/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.cursor/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.cursor/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.cursor/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.cursor/skills/yss-repository/SKILL.md +28 -70
- package/template/.cursor/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.cursor/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.cursor/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.cursor/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.cursor/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.cursor/skills/yss-research/SKILL.md +1 -1
- package/template/.cursor/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.cursor/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.cursor/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.cursor/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.pi/skills/code-review/SKILL.md +4 -0
- package/template/.pi/skills/code-review/agents/openai.yaml +1 -1
- package/template/.pi/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.pi/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.pi/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.pi/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.pi/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.pi/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.pi/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.pi/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.pi/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.pi/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.pi/skills/yss-repository/SKILL.md +28 -70
- package/template/.pi/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.pi/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.pi/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.pi/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.pi/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.pi/skills/yss-research/SKILL.md +1 -1
- package/template/.pi/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.pi/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.pi/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.pi/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.qoder/skills/code-review/SKILL.md +4 -0
- package/template/.qoder/skills/code-review/agents/openai.yaml +1 -1
- package/template/.qoder/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.qoder/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.qoder/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.qoder/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.qoder/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.qoder/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.qoder/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.qoder/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.qoder/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.qoder/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.qoder/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.qoder/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.qoder/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.qoder/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.qoder/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.qoder/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.qoder/skills/yss-repository/SKILL.md +28 -70
- package/template/.qoder/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.qoder/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.qoder/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.qoder/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.qoder/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.qoder/skills/yss-research/SKILL.md +1 -1
- package/template/.qoder/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.qoder/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.qoder/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.qoder/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.qoder/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.qoder/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.trae/skills/code-review/SKILL.md +4 -0
- package/template/.trae/skills/code-review/agents/openai.yaml +1 -1
- package/template/.trae/skills/code-review/references/yss-review-standards.md +9 -2
- package/template/.trae/skills/competitive-intelligence/SKILL.md +4 -4
- package/template/.trae/skills/domain-modeling/CONTEXT-FORMAT.md +1 -1
- package/template/.trae/skills/grill-with-docs/SKILL.md +1 -1
- package/template/.trae/skills/setup-matt-pocock-skills/issue-tracker-local.md +1 -1
- package/template/.trae/skills/yss-ddd-scaffold-generator/SKILL.md +1 -1
- package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/generate_scaffold.mjs +7 -3
- package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs +8 -8
- package/template/.trae/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs +9 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/SKILL.md +10 -7
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs +10 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/generate_scaffold.mjs +121 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +40 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +55 -0
- package/template/.trae/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.trae/skills/yss-implementation-contract-compiler/references/boundaries.md +4 -0
- package/template/.trae/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +25 -0
- package/template/.trae/skills/yss-layered-mvc-scaffold-generator/SKILL.md +2 -2
- package/template/.trae/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs +8 -5
- package/template/.trae/skills/yss-layered-mvc-scaffold-generator/scripts/scaffold-generator.test.mjs +17 -2
- package/template/.trae/skills/yss-mybatis/SKILL.md +34 -58
- package/template/.trae/skills/yss-mybatis/agents/openai.yaml +2 -2
- package/template/.trae/skills/yss-mybatis/references/source-index.md +88 -68
- package/template/.trae/skills/yss-product-lifecycle/SKILL.md +50 -42
- package/template/.trae/skills/yss-product-lifecycle/references/artifact-dependencies.md +5 -3
- package/template/.trae/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +124 -16
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration.md +16 -2
- package/template/.trae/skills/yss-product-lifecycle/references/state-model.md +5 -2
- package/template/.trae/skills/yss-repository/SKILL.md +28 -70
- package/template/.trae/skills/yss-repository/agents/openai.yaml +2 -2
- package/template/.trae/skills/yss-repository/references/profiles/layered-mvc-service.md +19 -1
- package/template/.trae/skills/yss-repository/references/profiles/mvc-data-analysis-v1.md +19 -1
- package/template/.trae/skills/yss-repository/references/profiles/target-domain-model.md +21 -1
- package/template/.trae/skills/yss-repository/tests/profile-routing.test.mjs +59 -0
- package/template/.trae/skills/yss-research/SKILL.md +1 -1
- package/template/.trae/skills/yss-skill-source-index-refresh/SKILL.md +8 -5
- package/template/.trae/skills/yss-skill-source-index-refresh/references/source-location.md +2 -1
- package/template/.trae/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.mjs +388 -18
- package/template/.trae/skills/yss-skill-source-index-refresh/scripts/refresh-yss-skill-index.test.mjs +79 -1
- package/template/.trae/skills/yss-stage-decision/SKILL.md +5 -3
- package/template/.trae/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/AGENTS.md +2 -2
- package/template/CONTEXT.md +3 -2
- package/template/README.md +3 -3
- package/template/docs/agents/digital-human-roles.md +1 -1
- package/template/docs/agents/digital-human-roles.yaml +13 -11
- package/template/docs/agents/issue-tracker.md +1 -1
- package/template/docs/agents/strategic-design-skills-integration.md +2 -0
- package/template/docs/agents/yss-skill-registry.yaml +5 -0
- package/template/docs/architecture/README.md +1 -1
- package/template/docs/architecture/templates/business-architecture-template.md +1 -1
- package/template/docs/architecture/templates/functional-architecture-template.md +1 -1
- package/template/docs/design/README.md +1 -1
- package/template/docs/design/templates/interaction-spec-template.md +1 -1
- package/template/docs/design/templates/product-overview-design-template.md +1 -1
- package/template/docs/{discovery → plan}/IDEATION.md +5 -5
- package/template/docs/plan/README.md +9 -0
- package/template/docs/plan/entry-review.md +23 -0
- package/template/docs/plan/templates/plan-template.md +58 -0
- package/template/docs/process/harness-process-tailoring.md +1 -1
- package/template/docs/process/lifecycle-artifact-map.md +10 -6
- package/template/docs/process/lifecycle-registry-baseline.json +10 -1
- package/template/docs/process/lifecycle-registry.yaml +48 -20
- package/template/docs/process/plan-migration.md +13 -0
- package/template/docs/process/schemas/digital-human-task-package.schema.json +2 -0
- package/template/docs/process/schemas/implementation-repository-preparation-result.schema.json +38 -0
- package/template/docs/process/schemas/lifecycle-checkpoint.schema.json +3 -0
- package/template/docs/process/schemas/lifecycle-registry.schema.json +1 -1
- package/template/docs/process/schemas/project-scaffold-contract.schema.json +113 -0
- package/template/docs/process/template-engineering-overview.md +2 -2
- package/template/docs/process/template-verification-profiles.yaml +25 -0
- package/template/docs/process/templates/context-reconciliation-template.yaml +2 -2
- package/template/docs/process/templates/lifecycle-checkpoint-template.yaml +1 -1
- package/template/docs/requirements/README.md +2 -2
- package/template/docs/templates/implementation-repo-registry-template.md +8 -0
- package/template/docs/templates/local-parent-ticket-template.md +1 -1
- package/template/docs/templates/review-report-template.md +7 -3
- package/template/docs/templates/subagent-task-package-template.md +1 -1
- package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +1 -1
- package/template/scripts/cache-template-commit +2 -2
- package/template/scripts/fixtures/strategic-handoff/source-roles.json +7 -7
- package/template/scripts/fixtures/user-decision/plan-fixture.mjs +30 -0
- package/template/scripts/lib/backend-delivery.mjs +5 -2
- package/template/scripts/lib/command-runner.mjs +107 -0
- package/template/scripts/lib/context-reconciliation.mjs +34 -0
- package/template/scripts/lib/json-schema.mjs +42 -13
- package/template/scripts/lib/lifecycle-context-query.mjs +141 -0
- package/template/scripts/lib/lifecycle-transition.mjs +118 -6
- package/template/scripts/lib/plan-spec-entry.mjs +87 -0
- package/template/scripts/lib/scenario-checks.mjs +44 -38
- package/template/scripts/lib/skill-registry.mjs +9 -0
- package/template/scripts/lib/skill-supply-chain.mjs +18 -2
- package/template/scripts/lib/strategic-handoff-io.mjs +5 -4
- package/template/scripts/lib/strategic-handoff.mjs +10 -9
- package/template/scripts/lib/task-package.mjs +2 -0
- package/template/scripts/lib/template-commit-cache.mjs +7 -5
- package/template/scripts/query-lifecycle-context +25 -0
- package/template/scripts/run-template-verification +9 -3
- package/template/scripts/sync-strategic-handoff-tools +9 -0
- package/template/scripts/verify-business-language-scenarios +0 -7
- package/template/scripts/verify-context-reconciliation +2 -48
- package/template/scripts/verify-context-reconciliation-scenarios +1 -1
- package/template/scripts/verify-frontend-scaffold-generator-scenarios +2 -0
- package/template/scripts/verify-lifecycle-checkpoint +2 -0
- package/template/scripts/verify-lifecycle-context-query-scenarios +88 -0
- package/template/scripts/verify-lifecycle-transition-scenarios +44 -4
- package/template/scripts/verify-plan-spec-entry +11 -0
- package/template/scripts/verify-plan-spec-entry-scenarios +79 -0
- package/template/scripts/verify-script-performance-scenarios +56 -0
- package/template/scripts/verify-subagent-task-package-scenarios +9 -8
- package/template/scripts/verify-template-cache-scenarios +11 -1
- package/template/scripts/verify-user-decision-scenarios +4 -4
- package/template/skills-lock.json +23 -23
- package/template.manifest.json +2 -1
- package/template.snapshot.json +5 -5
- package/template/.agents/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.agents/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.agents/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.agents/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.agents/skills/yss-mybatis/references/README.md +0 -57
- package/template/.agents/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.claude/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.claude/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.claude/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.claude/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.claude/skills/yss-mybatis/references/README.md +0 -57
- package/template/.claude/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.codex/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.codex/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.codex/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.codex/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.codex/skills/yss-mybatis/references/README.md +0 -57
- package/template/.codex/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.cursor/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.cursor/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.cursor/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.cursor/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.cursor/skills/yss-mybatis/references/README.md +0 -57
- package/template/.cursor/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.pi/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.pi/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.pi/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.pi/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.pi/skills/yss-mybatis/references/README.md +0 -57
- package/template/.pi/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.qoder/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.qoder/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.qoder/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.qoder/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.qoder/skills/yss-mybatis/references/README.md +0 -57
- package/template/.qoder/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/.trae/skills/yss-mybatis/assets/BaseRepository.java +0 -112
- package/template/.trae/skills/yss-mybatis/assets/EntityQueryAspect.java +0 -37
- package/template/.trae/skills/yss-mybatis/assets/MybatisBaseConfiguration.java +0 -18
- package/template/.trae/skills/yss-mybatis/assets/PageQueryEntityConfigration.java +0 -18
- package/template/.trae/skills/yss-mybatis/references/README.md +0 -57
- package/template/.trae/skills/yss-repository/references/infrastructure-layer-guide.md +0 -107
- package/template/docs/discovery/README.md +0 -87
- package/template/docs/discovery/reports/.gitkeep +0 -0
- package/template/docs/discovery/reports/agent-governance-options.md +0 -71
- package/template/docs/discovery/reports/competitor-deep-dive/.gitkeep +0 -0
- package/template/docs/discovery/templates/discovery-template.md +0 -94
- /package/template/docs/{discovery → plan}/templates/competitive-analysis-template.md +0 -0
- /package/template/docs/{discovery → plan}/templates/competitive-matrix-template.md +0 -0
- /package/template/docs/{discovery → plan}/templates/market-analysis-template.md +0 -0
- /package/template/docs/{discovery → plan}/templates/user-pain-points-template.md +0 -0
|
@@ -11,7 +11,7 @@ Call the Skill tool with `grilling`, then call it separately with `domain-modeli
|
|
|
11
11
|
1. Read `yss-project.yaml` and the root glossary before the first round, then run `scripts/verify-context-contract --root . --json`. Missing or lowercase root files, nested `CONTEXT.md`, `CONTEXT-MAP.md`, unsupported schema, absolute/cross-repository references, and Markdown pseudo-anchors are `blocked` or `migration-required`.
|
|
12
12
|
2. Separate discoverable facts from user decisions; investigate facts instead of asking the user.
|
|
13
13
|
3. Ask the entire current decision frontier, with a recommendation for every question, then wait.
|
|
14
|
-
4. Keep candidate or disputed terms in the
|
|
14
|
+
4. Keep candidate or disputed terms in the Plan decision frontier. Only after confirmation, use `domain-modeling` to record true stable glossary entries in the repository root's single, case-sensitive `CONTEXT.md`; business rows use the five-column format and `<ContextId>/<EnglishIdentifier>` identity. Non-`Global` Context IDs must come from the approved business responsibility areas in the business-boundary asset.
|
|
15
15
|
5. Create an ADR only when the decision is hard to reverse, surprising without context, and a real trade-off.
|
|
16
16
|
6. Persist factual research/validation records in the repository's existing review or research convention.
|
|
17
17
|
7. For `project-instance`, before requesting approval or returning a next work unit, generate and validate `context_reconciliation` with a readable ref, `document_digest`, `referenced_terms_digest`, and `term_refs`. Unresolved candidates, scope conflicts, aliases, or digest drift are `blocked`; reconciliation does not create another gate. For `template-source`, do not add fictional business terms and return a reasoned `not-applicable` after validating the template contract.
|
|
@@ -88,7 +88,7 @@ node scripts/run_first_slice_verification.mjs \
|
|
|
88
88
|
- 生成后的后端工程必须使用项目根目录 `./mvnw ...` 执行构建、测试、运行和 CI 验证;不得在 README、实施记录、Ticket、Review 或 Release 中默认写裸 `mvn ...`。既有仓库确实无法使用 wrapper 时,必须记录受控例外。
|
|
89
89
|
- 原型确认后,`scaffold_status=required` 才能进入本 skill;本 skill 的生成边界是工程结构、POM、配置、Wrapper 和机械模板,不是业务实现。
|
|
90
90
|
- 脚手架合同必须携带 `contract_id`、`contract_version`、实现合同编译器 draft 引用、生命周期批准引用、持久化引用、当前版本、允许写路径、预期证据文件和验证命令;字段缺失或版本过期时阻断。
|
|
91
|
-
-
|
|
91
|
+
- 新脚手架优先接受统一 Project Scaffold Contract schema v4;已批准且当前的后端 schema v3 可完成兼容生成。两者都必须携带 `architecture_family=domain-driven`、`generator_skill`、`decision_ref/id/digest`、固定模块闭包,以及 `project_name`、`base_package` 和 `maven_coordinates`。历史 schema v2 仅只读兼容,不用于新生成;schema v1/v2 均不自动升级。
|
|
92
92
|
- 合同 `profiles` 只支持 `target-domain-model`、`mybatis-plus`、`mysql`、`spring-boot-2.7-jdk8`、`javax`、`web`、`yss-internal`。普通 MyBatis、Boot 3、独立 client module、client-in-domain 和其他旧架构均为 `unsupported`,不提供回退分支。
|
|
93
93
|
- 运行生成器必须传入 `--contract-file`;生成器会校验合同 `status=approved`、`current_version`、`primary_skill`、`controlled-generation`、实际输出路径和固定三条验证命令,不接受仅凭任意字符串引用的放行。
|
|
94
94
|
- 生成项目必须写入 Manifest v3 `.yss/scaffold-generation.json`,记录架构选择及 digest、生成器、合同 digest、Target Profile、模块闭包、模板 digest、下游完整 skill tree digest、脚手架父合同与 实现合同编译器 合同 digest、generator-owned 文件 hash、严格 `generation_policy` 和完成等级;清单缺失或不一致时不得交给后续 实现合同编译器。
|
|
@@ -9,6 +9,7 @@ import { fileURLToPath } from "node:url";
|
|
|
9
9
|
import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
|
|
10
10
|
import { assertLocalDatabaseProfile, localDatabaseConfiguration, scaffoldArchitectureIdentity } from "../../../../scripts/lib/scaffold-local-database.mjs";
|
|
11
11
|
import { validateArchitectureIdentity } from "../../../../scripts/lib/backend-architecture.mjs";
|
|
12
|
+
import { validateJsonSchema } from "../../../../scripts/lib/json-schema.mjs";
|
|
12
13
|
|
|
13
14
|
import {
|
|
14
15
|
findGitRoot,
|
|
@@ -204,7 +205,9 @@ class ScaffoldGenerator {
|
|
|
204
205
|
const contractText = await readFile(this.contractFile, "utf8");
|
|
205
206
|
let contract; try { contract = JSON.parse(contractText); } catch { fail(`脚手架合同文件无法读取或不是合法 JSON: ${this.contractFile}`); }
|
|
206
207
|
if (!contract || Array.isArray(contract) || typeof contract !== "object") fail("脚手架合同必须是 JSON 对象");
|
|
207
|
-
if (contract.schema_version
|
|
208
|
+
if (![3, 4].includes(contract.schema_version)) fail(`unsupported: scaffold contract schema_version=${contract.schema_version};只接受兼容 v3 或统一 v4`);
|
|
209
|
+
if (contract.schema_version === 4 && (contract.kind !== "project-scaffold-contract" || contract.delivery_role !== "backend" || contract.scaffold_kind !== "backend-ddd")) fail("schema v4 合同必须绑定 backend/backend-ddd");
|
|
210
|
+
if (contract.schema_version === 4) validateJsonSchema(contract, path.join(REPOSITORY_ROOT, "docs/process/schemas/project-scaffold-contract.schema.json"), { label: "Project Scaffold Contract v4" });
|
|
208
211
|
const requiredMetadata = [["--contract-id", this.options.contractId], ["--contract-version", this.options.contractVersion], ["--approval-ref", this.options.approvalRef], ["--compiler-draft-ref", this.options.compilerDraftRef], ["--persisted-ref", this.options.persistedRef]];
|
|
209
212
|
const missing = requiredMetadata.filter(([, value]) => !isPresent(value)).map(([flag]) => flag);
|
|
210
213
|
if (missing.length) fail(`生成项目必须提供当前已批准脚手架合同的完整元数据: ${missing.join(", ")}`);
|
|
@@ -214,7 +217,7 @@ class ScaffoldGenerator {
|
|
|
214
217
|
if (contract.status !== "approved") fail("脚手架合同必须已由生命周期批准");
|
|
215
218
|
if (contract.contract_id !== this.options.contractId) fail("--contract-id 与脚手架合同不一致");
|
|
216
219
|
if (contract.contract_version !== this.options.contractVersion) fail("--contract-version 与脚手架合同不一致");
|
|
217
|
-
if (contract.current_version !== contract.contract_version) fail("脚手架合同版本不是当前版本");
|
|
220
|
+
if (contract.current_version !== contract.contract_version && !(contract.schema_version === 4 && contract.current_version === true)) fail("脚手架合同版本不是当前版本");
|
|
218
221
|
if (contract.compiler_draft_ref !== this.options.compilerDraftRef) fail("--compiler-draft-ref 与脚手架合同不一致");
|
|
219
222
|
if (contract.persisted_ref !== this.options.persistedRef) fail("--persisted-ref 与脚手架合同不一致");
|
|
220
223
|
if (contract.lifecycle_approval_ref !== this.options.approvalRef) fail("--approval-ref 与脚手架合同不一致");
|
|
@@ -364,6 +367,7 @@ class ScaffoldGenerator {
|
|
|
364
367
|
const scaffoldParent = path.join(SKILL_ROOT, "references", "yss-backend-scaffold-parent", "SKILL.md");
|
|
365
368
|
const compilerContract = path.join(REPOSITORY_ROOT, ".agents", "skills", "yss-implementation-contract-compiler", "references", "compiler-contract.yaml");
|
|
366
369
|
const manifest = { schema_version: 3, kind: "backend-scaffold", architecture_profile: contract.architecture_profile, architecture_identity: scaffoldArchitectureIdentity(contract, this.contractDigest), contract_id: this.options.contractId, contract_version: this.options.contractVersion, scaffold_request_id: contract.scaffold_request_id, architecture_family: contract.architecture_family, generator_skill: contract.generator_skill, decision_id: contract.decision_id, decision_digest: contract.decision_digest, module_profile: contract.module_profile, approval_ref: this.options.approvalRef, compiler_draft_ref: this.options.compilerDraftRef, persisted_ref: this.options.persistedRef, contract_file_ref: this.contractFile, contract_digest: this.contractDigest, lifecycle_approval_ref: contract.lifecycle_approval_ref, current_version: contract.current_version, approver: contract.approval.approver, allowed_write_paths: contract.allowed_write_paths, expected_evidence_files: contract.expected_evidence_files, project_name: this.projectName, base_package: this.basePackage, bootstrap_main_class: `${this.basePackage}.${this.applicationClassName}`, bootstrap_main_source: this.bootstrapMainSource, maven_coordinates: this.mavenCoordinates, maven_coordinates_source: this.mavenCoordinatesSource, profiles: this.profiles, generation_mode: "controlled-generation", completion_level: "generated", generator: { id: "yss-ddd-scaffold-generator", template_digest: await treeDigest(path.join(SKILL_ROOT, "assets")) }, ownership: { generated_files: generatedFiles, user_owned_globs: ["**/src/main/java/**", "**/src/test/java/**", "db/**"] }, readiness: { downstream_skills: downstream, contracts: { scaffold_parent: sha256(await readFile(scaffoldParent)), compiler_contract: sha256(await readFile(compilerContract)) }, architecture_ruleset: sha256(await readFile(path.join(this.javaTemplateDir, "architecture-rules-test.java.template"))) }, generation_policy: { mode: "initialize-only", existing_target: "unsupported", old_project_migration: "unsupported", template_upgrade: "unsupported" }, verification_commands: COMMANDS, generated_at: isoNow() };
|
|
370
|
+
manifest.schema_version = contract.schema_version;
|
|
367
371
|
await writeText(path.join(this.projectRoot, ".yss", "scaffold-generation.json"), `${JSON.stringify(manifest, null, 2)}\n`); console.log(" ✓ .yss/scaffold-generation.json");
|
|
368
372
|
}
|
|
369
373
|
async copyWrapperFiles() {
|
|
@@ -375,7 +379,7 @@ class ScaffoldGenerator {
|
|
|
375
379
|
const required = [path.join(this.projectRoot, "pom.xml"), path.join(this.projectRoot, `${this.projectName}-bootstrap`, "pom.xml"), path.join(this.projectRoot, this.bootstrapMainSource), path.join(this.projectRoot, "mvnw"), path.join(this.projectRoot, ".yss", "scaffold-generation.json")];
|
|
376
380
|
const missing = []; for (const target of required) if (!await isFile(target)) missing.push(target); if (missing.length) fail(`生成产物缺失: ${missing.join(", ")}`);
|
|
377
381
|
const manifest = await readJson(required[4], "脚手架生成元数据清单无法读取");
|
|
378
|
-
if (manifest.schema_version
|
|
382
|
+
if (![3, 4].includes(manifest.schema_version) || manifest.contract_id !== this.options.contractId || manifest.contract_version !== this.options.contractVersion || (manifest.current_version !== this.options.contractVersion && manifest.current_version !== true) || manifest.generation_mode !== "controlled-generation" || manifest.architecture_family !== "domain-driven" || manifest.generator_skill !== "yss-ddd-scaffold-generator" || manifest.decision_id !== this.scaffoldContract.decision_id || manifest.decision_digest !== this.scaffoldContract.decision_digest || JSON.stringify(manifest.module_profile) !== JSON.stringify(this.scaffoldContract.module_profile) || manifest.bootstrap_main_class !== `${this.basePackage}.${this.applicationClassName}` || manifest.bootstrap_main_source !== this.bootstrapMainSource || manifest.profiles.architecture !== SUPPORTED_PROFILES.architecture || manifest.generation_policy.mode !== "initialize-only" || manifest.generation_policy.existing_target !== "unsupported" || JSON.stringify(manifest.verification_commands) !== JSON.stringify(COMMANDS)) fail("脚手架生成元数据清单与当前批准架构决策、合同、Target Profile、initialize-only 边界、机械启动入口或固定验证命令不一致");
|
|
379
383
|
const stack = [this.projectRoot], binary = new Set([".class", ".db", ".jar", ".png", ".jpg", ".jpeg", ".gif"]);
|
|
380
384
|
while (stack.length) { const dir = stack.pop(); for (const entry of await readdir(dir, { withFileTypes: true })) { const target = path.join(dir, entry.name); if (entry.isDirectory()) { stack.push(target); continue; } if (!entry.isFile() || binary.has(path.extname(entry.name))) continue; const content = await readFile(target, "utf8"); if (content.includes("{{") || content.includes("root/root")) fail(`生成文件包含未替换占位符或明文凭据: ${target}`); } }
|
|
381
385
|
}
|
package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
|
-
import {
|
|
6
|
+
import { runCommand } from "../../../../scripts/lib/command-runner.mjs";
|
|
7
7
|
import { assertArchitectureAgreement } from "../../../../scripts/lib/backend-architecture.mjs";
|
|
8
8
|
import { assertLocalDatabaseProfile, scaffoldArchitectureIdentity } from "../../../../scripts/lib/scaffold-local-database.mjs";
|
|
9
9
|
|
|
@@ -37,9 +37,9 @@ function classifyFailure(phase, outcome) {
|
|
|
37
37
|
if (phase === "package") return "packaging";
|
|
38
38
|
return "maven-execution";
|
|
39
39
|
}
|
|
40
|
-
function parseArgs(argv) { const result = {}; for (let index = 0; index < argv.length; index += 1) { let token = argv[index]; if (token === "--help" || token === "-h") { result.help = true; continue; } const equals = token.indexOf("="); let value; if (equals !== -1) { value = token.slice(equals + 1); token = token.slice(0, equals); } if (!["--project-root", "--evidence-dir"].includes(token)) throw new Error(`不支持的参数: ${token}`); if (value === undefined) value = argv[++index]; if (!value || value.startsWith("--")) throw new Error(`参数 ${token} 缺少值`); result[token === "--project-root" ? "projectRoot" : "evidenceDir"] = path.resolve(value); } if (result.help) return result; if (!result.projectRoot || !result.evidenceDir) throw new Error("必须提供 --project-root 和 --evidence-dir"); return result; }
|
|
40
|
+
function parseArgs(argv) { const result = {}; for (let index = 0; index < argv.length; index += 1) { let token = argv[index]; if (token === "--help" || token === "-h") { result.help = true; continue; } const equals = token.indexOf("="); let value; if (equals !== -1) { value = token.slice(equals + 1); token = token.slice(0, equals); } if (!["--project-root", "--evidence-dir", "--timeout-ms"].includes(token)) throw new Error(`不支持的参数: ${token}`); if (value === undefined) value = argv[++index]; if (!value || value.startsWith("--")) throw new Error(`参数 ${token} 缺少值`); if (token === "--timeout-ms") result.timeoutMs = Number(value); else result[token === "--project-root" ? "projectRoot" : "evidenceDir"] = path.resolve(value); } if (result.help) return result; if (!result.projectRoot || !result.evidenceDir) throw new Error("必须提供 --project-root 和 --evidence-dir"); return result; }
|
|
41
41
|
function validateManifest(manifest) {
|
|
42
|
-
if (![2, 3].includes(manifest.schema_version)) throw new Error(`unsupported: scaffold Manifest schema_version=${manifest.schema_version};只读兼容 v2,并验证当前 v3`);
|
|
42
|
+
if (![2, 3, 4].includes(manifest.schema_version)) throw new Error(`unsupported: scaffold Manifest schema_version=${manifest.schema_version};只读兼容 v2,并验证当前 v3/v4`);
|
|
43
43
|
const required = ["schema_version", "contract_id", "contract_version", "scaffold_request_id", "contract_digest", "profiles", "ownership", "readiness", "generation_policy", "completion_level", "approval_ref", "approver", "lifecycle_approval_ref", "compiler_draft_ref", "persisted_ref", "contract_file_ref", "current_version", "allowed_write_paths", "expected_evidence_files", "verification_commands", "generation_mode"];
|
|
44
44
|
if (manifest.schema_version === 3) required.push("architecture_family", "generator_skill", "decision_id", "decision_digest", "module_profile");
|
|
45
45
|
const missing = required.filter((field) => manifest[field] === undefined || manifest[field] === null || manifest[field] === "");
|
|
@@ -57,8 +57,7 @@ function validateManifest(manifest) {
|
|
|
57
57
|
if (manifest.current_version !== manifest.contract_version) throw new Error("脚手架生成元数据清单不是当前合同版本");
|
|
58
58
|
if (JSON.stringify(manifest.verification_commands) !== JSON.stringify(COMMANDS)) throw new Error("脚手架生成元数据清单验证命令不符合固定合同");
|
|
59
59
|
}
|
|
60
|
-
|
|
61
|
-
export async function run(projectRoot, evidenceDir, environment = process.env) {
|
|
60
|
+
export async function run(projectRoot, evidenceDir, environment = process.env, { timeoutMs = 0, signal } = {}) {
|
|
62
61
|
const wrapper = path.join(projectRoot, "mvnw"), manifestPath = path.join(projectRoot, ".yss", "scaffold-generation.json");
|
|
63
62
|
if (!await isFile(wrapper)) throw new Error(`项目根目录缺少 Maven wrapper: ${wrapper}`);
|
|
64
63
|
if (!await isFile(manifestPath)) throw new Error(`项目根目录缺少脚手架生成元数据清单: ${manifestPath}`);
|
|
@@ -91,7 +90,8 @@ export async function run(projectRoot, evidenceDir, environment = process.env) {
|
|
|
91
90
|
const stderrPath = path.join(evidenceDir, `mvnw-${phase}.stderr.log`);
|
|
92
91
|
const startedAt = isoNow();
|
|
93
92
|
const started = process.hrtime.bigint();
|
|
94
|
-
const
|
|
93
|
+
const execution = await runCommand(wrapper, [phase], { cwd: projectRoot, env: environment, timeoutMs, signal, stdoutFile: stdoutPath, stderrFile: stderrPath, secrets: [environment.MAVEN_REPO_USERNAME, environment.MAVEN_REPO_PASSWORD], progress: true });
|
|
94
|
+
const outcome = { ...execution, exitCode: execution.status };
|
|
95
95
|
const durationMs = Number(process.hrtime.bigint() - started) / 1e6;
|
|
96
96
|
await writeText(stdoutPath, redactSecrets(outcome.stdout, environment));
|
|
97
97
|
await writeText(stderrPath, redactSecrets(outcome.stderr, environment));
|
|
@@ -99,7 +99,7 @@ export async function run(projectRoot, evidenceDir, environment = process.env) {
|
|
|
99
99
|
command: `./mvnw ${phase}`,
|
|
100
100
|
phase,
|
|
101
101
|
exit_code: outcome.exitCode,
|
|
102
|
-
failure_category: classifyFailure(phase, outcome),
|
|
102
|
+
failure_category: outcome.termination || classifyFailure(phase, outcome),
|
|
103
103
|
duration_ms: Number(durationMs.toFixed(3)),
|
|
104
104
|
started_at: startedAt,
|
|
105
105
|
executed_at: isoNow(),
|
|
@@ -120,5 +120,5 @@ export async function run(projectRoot, evidenceDir, environment = process.env) {
|
|
|
120
120
|
commands
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
-
async function main() { let args; try { args = parseArgs(process.argv.slice(2)); if (args.help) { console.log("运行 YSS 脚手架真实验证命令\n用法: node scripts/run_scaffold_verification.mjs --project-root <dir> --evidence-dir <dir>"); return 0; } const reportPath = path.join(args.evidenceDir, "scaffold-verification.json"); try { const report = await run(args.projectRoot, args.evidenceDir); await writeText(reportPath, `${JSON.stringify(report, null, 2)}\n`); console.log(`${report.status}: ${reportPath}`); return report.status === "passed" ? 0 : 1; } catch (error) { const report = { verification_mode: "controlled-generation", project_root: args.projectRoot, generated_at: isoNow(), status: "failed", failure_category: "verification-preflight", error: error.message, commands: [] }; await writeText(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stderr.write(`❌ 脚手架验证无法执行: ${error.message}\n`); return 1; } } catch (error) { process.stderr.write(`❌ 脚手架验证无法执行: ${error.message}\n`); return 1; } }
|
|
123
|
+
async function main() { let args; try { args = parseArgs(process.argv.slice(2)); if (args.help) { console.log("运行 YSS 脚手架真实验证命令\n用法: node scripts/run_scaffold_verification.mjs --project-root <dir> --evidence-dir <dir>"); return 0; } const reportPath = path.join(args.evidenceDir, "scaffold-verification.json"); try { const report = await run(args.projectRoot, args.evidenceDir, process.env, { timeoutMs: args.timeoutMs ?? 0 }); await writeText(reportPath, `${JSON.stringify(report, null, 2)}\n`); console.log(`${report.status}: ${reportPath}`); return report.status === "passed" ? 0 : 1; } catch (error) { const report = { verification_mode: "controlled-generation", project_root: args.projectRoot, generated_at: isoNow(), status: "failed", failure_category: "verification-preflight", error: error.message, commands: [] }; await writeText(reportPath, `${JSON.stringify(report, null, 2)}\n`); process.stderr.write(`❌ 脚手架验证无法执行: ${error.message}\n`); return 1; } } catch (error) { process.stderr.write(`❌ 脚手架验证无法执行: ${error.message}\n`); return 1; } }
|
|
124
124
|
if (process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href) process.exitCode = await main();
|
package/template/.cursor/skills/yss-ddd-scaffold-generator/scripts/scaffold-generator.test.mjs
CHANGED
|
@@ -140,6 +140,15 @@ async function prepareVerifierProject(project, manifest = targetManifest()) {
|
|
|
140
140
|
|
|
141
141
|
test("生成批准的服务级 target profile 骨架,并写入可追溯 Manifest v3", async (t) => { const data = await fixture(); t.after(() => rm(data.root, { recursive: true, force: true })); const result = await command(data.args); assert.equal(result.code, 0, result.stderr); const project = path.join(data.output, "demo-service"); const manifest = JSON.parse(await readFile(path.join(project, ".yss/scaffold-generation.json"), "utf8")); assert.equal(manifest.schema_version, 3); assert.equal(manifest.architecture_family, "domain-driven"); assert.equal(manifest.generator_skill, "yss-ddd-scaffold-generator"); assert.equal(manifest.decision_id, "scaffold-decision.demo-service"); assert.equal(manifest.scaffold_request_id, "scaffold-request-1"); assert.equal(manifest.slice_id, undefined); assert.equal(manifest.completion_level, "generated"); assert.equal(manifest.profiles.architecture, "target-domain-model"); assert.deepEqual(manifest.generation_policy, { mode: "initialize-only", existing_target: "unsupported", old_project_migration: "unsupported", template_upgrade: "unsupported" }); assert.match(manifest.generator.template_digest, /^[a-f0-9]{64}$/); assert.match(manifest.contract_digest, /^[a-f0-9]{64}$/); assert.ok(manifest.ownership.generated_files.length > 8); assert.ok(manifest.ownership.generated_files.every((item) => item.owner === "generator" && /^[a-f0-9]{64}$/.test(item.sha256))); assert.equal(manifest.generation_mode, "controlled-generation"); assert.deepEqual(manifest.verification_commands, ["./mvnw validate", "./mvnw test", "./mvnw package"]); assert.equal(manifest.bootstrap_main_class, "com.yss.demo.DemoServiceApplication"); assert.equal(manifest.bootstrap_main_source, "demo-service-bootstrap/src/main/java/com/yss/demo/DemoServiceApplication.java"); assert.match(await readFile(path.join(project, manifest.bootstrap_main_source), "utf8"), /class DemoServiceApplication/); assert.match(await readFile(path.join(project, "pom.xml"), "utf8"), /demo-service/); assert.equal(manifest.readiness.downstream_skills["yss-domain"], await treeDigest(path.resolve(scripts, "../../yss-domain"))); assert.match(manifest.readiness.contracts.scaffold_parent, /^[a-f0-9]{64}$/); assert.match(manifest.readiness.contracts.compiler_contract, /^[a-f0-9]{64}$/); });
|
|
142
142
|
|
|
143
|
+
test("统一 Project Scaffold Contract v4 可生成 DDD 后端并保留 v4 Manifest", async (t) => {
|
|
144
|
+
const data = await fixture({ schema_version: 4, kind: "project-scaffold-contract", delivery_role: "backend", scaffold_kind: "backend-ddd", repository_scope: "external-repository", init_git: false, current_version: true });
|
|
145
|
+
t.after(() => rm(data.root, { recursive: true, force: true }));
|
|
146
|
+
const result = await command(data.args);
|
|
147
|
+
assert.equal(result.code, 0, result.stderr);
|
|
148
|
+
const manifest = JSON.parse(await readFile(path.join(data.output, "demo-service", ".yss/scaffold-generation.json"), "utf8"));
|
|
149
|
+
assert.equal(manifest.schema_version, 4);
|
|
150
|
+
});
|
|
151
|
+
|
|
143
152
|
test("schema v1 scaffold contract is unsupported and is never upgraded", async (t) => {
|
|
144
153
|
const data = await fixture({ schema_version: 1 });
|
|
145
154
|
t.after(() => rm(data.root, { recursive: true, force: true }));
|
|
@@ -5,7 +5,7 @@ description: Use when creating a new YSS frontend micro-application from the sta
|
|
|
5
5
|
|
|
6
6
|
# YSS Frontend Scaffold Generator
|
|
7
7
|
|
|
8
|
-
用于从标准 YSS 前端模板创建 0-1
|
|
8
|
+
用于从标准 YSS 前端模板创建 0-1 前端微应用工程。它只在阶段 5 的 `work-unit.implementation-repository-preparation` 中消费生命周期批准、持久化且当前的 Project Scaffold Contract schema v4,执行 `controlled-generation`;不生成业务页面。
|
|
9
9
|
|
|
10
10
|
## Template Source
|
|
11
11
|
|
|
@@ -21,7 +21,8 @@ branch: template
|
|
|
21
21
|
- `app_name`:应用名。
|
|
22
22
|
- `microapp_name`:微应用注册名。
|
|
23
23
|
- `base_route`:基础路由。
|
|
24
|
-
-
|
|
24
|
+
- Project Scaffold Contract schema v4:包含用户确认的仓库 scope、目标路径、`init_git`、模板 commit、应用参数、允许写路径和验证命令。
|
|
25
|
+
- OpenAPI Freeze 记录:有 API 影响时提供已批准的冻结 YAML 版本和引用;无 API 影响时提供带原因的 `not-applicable`。
|
|
25
26
|
- OpenAPI JSON 派生记录:`docs/.scratch/<feature>/api/<feature>-json-export.md`,包含 YAML / JSON SHA-256、Redocly CLI 版本和 lockfile 引用。
|
|
26
27
|
- 冻结 JSON 产物:`docs/.scratch/<feature>/api/<feature>.json`;这是唯一允许交给既有前端代码生成流程的上游产物。
|
|
27
28
|
- `target_git_url` 或 `output_dir`:目标实现仓库或本地输出目录。
|
|
@@ -32,14 +33,14 @@ branch: template
|
|
|
32
33
|
|
|
33
34
|
采用专职前端 profile 或显式 `frontend_delivery` 绑定时,先按 `docs/process/frontend-backend-delivery.md` 实际核验战略与后端联合交付。缺任一输入只能诊断和回交;输入通过后准备计划/合同,正式实现、生成和恢复仍须当前批准的 Slice Contract 冻结接收摘要。接口或部署版本漂移时重新接收,不复用旧成功输出。
|
|
34
35
|
|
|
35
|
-
1. 确认当前任务已经通过 Harness
|
|
36
|
+
1. 确认当前任务已经通过 Harness 入口分诊、逐项目脚手架决定已由真实用户确认,且 schema v4 合同已由生命周期批准、持久化并保持当前。
|
|
36
37
|
2. 确认目标是外部实现仓库;只有用户明确选择时才输出到 Harness 仓库的 `apps/frontend/<project>/`。`apps/frontend/` 只能作为项目容器,`app/frontend/`、`app/backend/` 及其子路径禁止作为输出位置。`git-submodule` 只能在已初始化且附加分支的子仓工作树生成;空 gitlink、detached HEAD、`--force` 覆盖挂载点不得当成普通目录。
|
|
37
|
-
3.
|
|
38
|
-
4.
|
|
38
|
+
3. 只读检查模板分支和合同锁定的 40 位 commit 是否可访问;生成时使用精确 commit,不跟随浮动分支。
|
|
39
|
+
4. 使用 `scripts/generate_and_verify_scaffold.mjs` 从已核验 checkout 的批准 commit 导出模板,排除模板 `.git` 及未提交的工作树内容;目标必须不存在或为空。不得默认写入 Harness、不得 `--force`。仅合同 `init_git=true` 时初始化目标 Git。
|
|
39
40
|
5. 替换应用名、微应用名、路由、`micro-config.json`、环境变量和 README 中的模板占位。
|
|
40
|
-
6.
|
|
41
|
+
6. 有 API 影响时核验 OpenAPI Freeze 记录和 JSON 派生记录,将摘要一致的 JSON 原样物化到 `<frontend>/openapi/openapi.json`;`openapi_impact=not-applicable` 时必须有原因并禁止生成 API client。
|
|
41
42
|
7. 保持模板既有的前端代码生成配置不变;本 Harness 只将 SHA-256 一致的 JSON 原样交给既有前端代码生成流程,不修改该配置、不在此仓库执行生成,也不设置生成 CI 门禁。目标前端项目在需要时手动运行其既有命令。
|
|
42
|
-
8.
|
|
43
|
+
8. 实际执行并记录 `pnpm install --frozen-lockfile`、`pnpm lint`、`pnpm type-check`、`pnpm build` 的退出码和日志;缺失脚本只能由批准的工程基线提供替代命令。任何必需命令失败都阻断。
|
|
43
44
|
9. 按 `docs/templates/implementation-repo-registry-template.md` 回写前端实现仓库登记。
|
|
44
45
|
|
|
45
46
|
## Expected Template Shape
|
|
@@ -59,6 +60,7 @@ packages/package.json
|
|
|
59
60
|
## Boundaries
|
|
60
61
|
|
|
61
62
|
- 不直接创建远端 Git 项目,除非用户明确要求。
|
|
63
|
+
- 不保留模板 `.git` 或模板 remote;不在未获确认时执行 `git init`。
|
|
62
64
|
- 不推送、不创建 MR / PR,除非用户明确要求。
|
|
63
65
|
- 不绕过 OpenAPI Draft / Freeze;API client 只消费与 OpenAPI JSON 派生记录 SHA-256 一致的冻结 JSON。
|
|
64
66
|
- 不接受任意 URL、未冻结 YAML、后端运行时输出或手工 JSON 作为既有前端代码生成流程的输入。
|
|
@@ -75,4 +77,5 @@ packages/package.json
|
|
|
75
77
|
- install / lint / type-check / build 命令,以及目标前端项目既有的手动客户端生成命令(如有)。
|
|
76
78
|
- OpenAPI Freeze 记录、OpenAPI JSON 派生记录、JSON SHA-256 和 `openapi/openapi.json` 物化证据。
|
|
77
79
|
- Harness 实现仓库登记草案。
|
|
80
|
+
- `.yss/scaffold-generation.json` Manifest v4 与 `scaffold-verification.json`。
|
|
78
81
|
- 未覆盖项和 `TODO-HUMAN-REVIEW`。
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { generate } from "./generate_scaffold.mjs";
|
|
3
|
+
import { verify } from "./run_scaffold_verification.mjs";
|
|
4
|
+
function argsOf(argv) { const args = {}; for (let i = 0; i < argv.length; i += 2) args[argv[i].replace(/^--/, "")] = argv[i + 1]; return args; }
|
|
5
|
+
try {
|
|
6
|
+
const args = argsOf(process.argv.slice(2));
|
|
7
|
+
generate({ contractFile: args["contract-file"], templateCheckout: args["template-checkout"], outputDir: args["output-dir"] });
|
|
8
|
+
const report = verify(args["output-dir"], args["evidence-dir"]);
|
|
9
|
+
if (report.status !== "passed") process.exitCode = 1;
|
|
10
|
+
} catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { validateJsonSchema } from "../../../../scripts/lib/json-schema.mjs";
|
|
9
|
+
|
|
10
|
+
const fail = (message) => { throw new TypeError(message); };
|
|
11
|
+
const REPOSITORY_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../../..");
|
|
12
|
+
const sha256 = (value) => `sha256:${createHash("sha256").update(value).digest("hex")}`;
|
|
13
|
+
function argsOf(argv) {
|
|
14
|
+
const args = {};
|
|
15
|
+
for (let i = 0; i < argv.length; i += 2) args[argv[i].replace(/^--/, "")] = argv[i + 1];
|
|
16
|
+
return args;
|
|
17
|
+
}
|
|
18
|
+
function git(cwd, ...args) {
|
|
19
|
+
const result = spawnSync("git", args, { cwd, encoding: "utf8" });
|
|
20
|
+
if (result.status !== 0) fail(result.stderr || `git ${args.join(" ")} failed`);
|
|
21
|
+
return result.stdout.trim();
|
|
22
|
+
}
|
|
23
|
+
function walk(root) {
|
|
24
|
+
return readdirSync(root, { withFileTypes: true }).flatMap((entry) => {
|
|
25
|
+
const item = path.join(root, entry.name);
|
|
26
|
+
return entry.isDirectory() ? walk(item) : entry.isFile() || entry.isSymbolicLink() ? [item] : [];
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function validate(contract, outputDir) {
|
|
30
|
+
validateJsonSchema(contract, path.join(REPOSITORY_ROOT, "docs/process/schemas/project-scaffold-contract.schema.json"), { label: "Project Scaffold Contract v4" });
|
|
31
|
+
if (contract.schema_version !== 4 || contract.kind !== "project-scaffold-contract") fail("frontend scaffold requires Project Scaffold Contract schema v4");
|
|
32
|
+
if (contract.status !== "approved" || contract.current_version !== true || !contract.persisted_ref) fail("scaffold contract must be approved, persisted and current");
|
|
33
|
+
if (contract.delivery_role !== "frontend" || contract.scaffold_kind !== "frontend-yss-vue3" || contract.generator_skill !== "yss-frontend-scaffold-generator") fail("contract is not for the YSS frontend generator");
|
|
34
|
+
if (path.resolve(contract.target_output_dir) !== outputDir) fail("output directory differs from approved contract");
|
|
35
|
+
if (contract.generation_policy?.mode !== "initialize-only" || contract.generation_policy?.existing_target !== "unsupported") fail("unsupported generation policy");
|
|
36
|
+
if (!contract.frontend?.template?.repository || !/^[a-f0-9]{40}$/.test(contract.frontend.template.commit || "")) fail("template repository and exact 40-character commit are required");
|
|
37
|
+
if (contract.frontend.openapi_impact === "frozen" && (!contract.frontend.openapi_json_ref || !contract.frontend.openapi_json_digest)) fail("frozen OpenAPI JSON and digest are required");
|
|
38
|
+
if (contract.frontend.openapi_impact === "not-applicable" && !contract.frontend.openapi_not_applicable_reason) fail("no-API scaffold requires a reason");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function generate({ contractFile, templateCheckout, outputDir }) {
|
|
42
|
+
const contract = JSON.parse(readFileSync(contractFile, "utf8"));
|
|
43
|
+
outputDir = path.resolve(outputDir);
|
|
44
|
+
templateCheckout = path.resolve(templateCheckout);
|
|
45
|
+
validate(contract, outputDir);
|
|
46
|
+
if (!existsSync(path.join(templateCheckout, ".git"))) fail("template checkout must be a Git worktree");
|
|
47
|
+
if (git(templateCheckout, "rev-parse", "HEAD") !== contract.frontend.template.commit) fail("template checkout does not match approved commit");
|
|
48
|
+
if (git(templateCheckout, "config", "--get", "remote.origin.url") !== contract.frontend.template.repository) fail("template repository differs from approved source");
|
|
49
|
+
if (existsSync(outputDir) && readdirSync(outputDir).length > 0) fail("target directory must not exist or must be empty");
|
|
50
|
+
mkdirSync(outputDir, { recursive: true });
|
|
51
|
+
const scratch = mkdtempSync(path.join(tmpdir(), "yss-frontend-source-"));
|
|
52
|
+
try {
|
|
53
|
+
// Read the approved Git tree, never dependency caches or edits in the checkout.
|
|
54
|
+
const archive = spawnSync("git", ["archive", contract.frontend.template.commit], { cwd: templateCheckout, maxBuffer: 256 * 1024 * 1024 });
|
|
55
|
+
if (archive.error || archive.status !== 0) fail(archive.error?.message || String(archive.stderr));
|
|
56
|
+
const unpack = spawnSync("tar", ["-xf", "-", "-C", scratch], { input: archive.stdout });
|
|
57
|
+
if (unpack.error || unpack.status !== 0) fail(unpack.error?.message || String(unpack.stderr));
|
|
58
|
+
cpSync(scratch, outputDir, { recursive: true, verbatimSymlinks: true });
|
|
59
|
+
} finally { rmSync(scratch, { recursive: true, force: true }); }
|
|
60
|
+
|
|
61
|
+
const replacements = {
|
|
62
|
+
"__APP_NAME__": contract.frontend.app_name,
|
|
63
|
+
"__MICROAPP_NAME__": contract.frontend.microapp_name,
|
|
64
|
+
"__BASE_ROUTE__": contract.frontend.base_route,
|
|
65
|
+
...(contract.frontend.replacements || {}),
|
|
66
|
+
};
|
|
67
|
+
const generatedFiles = walk(outputDir).map(file => path.relative(outputDir, file));
|
|
68
|
+
for (const ref of generatedFiles) {
|
|
69
|
+
const file = path.join(outputDir, ref);
|
|
70
|
+
const info = lstatSync(file);
|
|
71
|
+
if (info.isSymbolicLink() || info.size > 2_000_000) continue;
|
|
72
|
+
const bytes = readFileSync(file);
|
|
73
|
+
if (bytes.includes(0) || !Buffer.from(bytes.toString("utf8")).equals(bytes)) continue;
|
|
74
|
+
const text = bytes.toString("utf8");
|
|
75
|
+
const replaced = Object.entries(replacements).reduce((value, [from, to]) => value.split(from).join(to), text);
|
|
76
|
+
if (replaced !== text) writeFileSync(file, replaced);
|
|
77
|
+
}
|
|
78
|
+
if (contract.frontend.openapi_impact === "frozen") {
|
|
79
|
+
const bytes = readFileSync(contract.frontend.openapi_json_ref);
|
|
80
|
+
if (sha256(bytes) !== contract.frontend.openapi_json_digest) fail("OpenAPI JSON digest mismatch");
|
|
81
|
+
mkdirSync(path.join(outputDir, "openapi"), { recursive: true });
|
|
82
|
+
writeFileSync(path.join(outputDir, "openapi", "openapi.json"), bytes);
|
|
83
|
+
if (!generatedFiles.includes("openapi/openapi.json")) generatedFiles.push("openapi/openapi.json");
|
|
84
|
+
}
|
|
85
|
+
if (contract.init_git === true) git(outputDir, "init");
|
|
86
|
+
generatedFiles.sort();
|
|
87
|
+
const manifest = {
|
|
88
|
+
schema_version: 4,
|
|
89
|
+
kind: "frontend-scaffold",
|
|
90
|
+
delivery_role: "frontend",
|
|
91
|
+
generator_skill: "yss-frontend-scaffold-generator",
|
|
92
|
+
contract_id: contract.contract_id,
|
|
93
|
+
contract_version: contract.contract_version,
|
|
94
|
+
contract_digest: sha256(readFileSync(contractFile)),
|
|
95
|
+
contract_file_ref: path.resolve(contractFile),
|
|
96
|
+
persisted_ref: contract.persisted_ref,
|
|
97
|
+
approval_ref: contract.approval.approval_ref,
|
|
98
|
+
template: { ...contract.frontend.template, checkout: templateCheckout },
|
|
99
|
+
repository_scope: contract.repository_scope,
|
|
100
|
+
target_output_dir: outputDir,
|
|
101
|
+
init_git: contract.init_git,
|
|
102
|
+
openapi_impact: contract.frontend.openapi_impact,
|
|
103
|
+
generation_mode: "controlled-generation",
|
|
104
|
+
generation_policy: contract.generation_policy,
|
|
105
|
+
verification_commands: contract.verification_commands,
|
|
106
|
+
generated_files: generatedFiles,
|
|
107
|
+
completion_level: "generated",
|
|
108
|
+
generated_at: new Date().toISOString(),
|
|
109
|
+
};
|
|
110
|
+
mkdirSync(path.join(outputDir, ".yss"), { recursive: true });
|
|
111
|
+
writeFileSync(path.join(outputDir, ".yss", "scaffold-generation.json"), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
112
|
+
return manifest;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
116
|
+
try {
|
|
117
|
+
const args = argsOf(process.argv.slice(2));
|
|
118
|
+
generate({ contractFile: args["contract-file"], templateCheckout: args["template-checkout"], outputDir: args["output-dir"] });
|
|
119
|
+
process.stdout.write("frontend scaffold generated\n");
|
|
120
|
+
} catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
121
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { runCommandSync } from "../../../../scripts/lib/command-runner.mjs";
|
|
5
|
+
|
|
6
|
+
const ALLOWED = new Map([
|
|
7
|
+
["pnpm install --frozen-lockfile", ["install", "--frozen-lockfile"]],
|
|
8
|
+
["pnpm lint", ["lint"]],
|
|
9
|
+
["pnpm type-check", ["type-check"]],
|
|
10
|
+
["pnpm build", ["build"]],
|
|
11
|
+
]);
|
|
12
|
+
function argsOf(argv) { const args = {}; for (let i = 0; i < argv.length; i += 2) args[argv[i].replace(/^--/, "")] = argv[i + 1]; return args; }
|
|
13
|
+
export function verify(projectRoot, evidenceDir, { timeoutMs = 0 } = {}) {
|
|
14
|
+
projectRoot = path.resolve(projectRoot); evidenceDir = path.resolve(evidenceDir);
|
|
15
|
+
const manifestPath = path.join(projectRoot, ".yss", "scaffold-generation.json");
|
|
16
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
17
|
+
if (manifest.schema_version !== 4 || manifest.kind !== "frontend-scaffold" || manifest.generation_mode !== "controlled-generation") throw new TypeError("invalid frontend scaffold manifest");
|
|
18
|
+
if (!manifest.generated_files.includes("pnpm-lock.yaml")) throw new TypeError("frontend template must contain pnpm-lock.yaml");
|
|
19
|
+
const commands = manifest.verification_commands;
|
|
20
|
+
for (const required of ALLOWED.keys()) if (!commands.includes(required)) throw new TypeError(`missing required verification command: ${required}`);
|
|
21
|
+
mkdirSync(evidenceDir, { recursive: true });
|
|
22
|
+
const results = commands.map((command, index) => {
|
|
23
|
+
const argv = ALLOWED.get(command);
|
|
24
|
+
if (!argv) throw new TypeError(`unsupported verification command: ${command}`);
|
|
25
|
+
const started = Date.now();
|
|
26
|
+
const stdoutRef = path.join(evidenceDir, `${index + 1}-stdout.log`), stderrRef = path.join(evidenceDir, `${index + 1}-stderr.log`);
|
|
27
|
+
const result = runCommandSync("pnpm", argv, { cwd: projectRoot, timeoutMs, stdoutFile: stdoutRef, stderrFile: stderrRef, progress: true });
|
|
28
|
+
return { command, exit_code: result.status ?? 1, duration_ms: Date.now() - started, ...(result.termination ? { termination: result.termination } : {}), stdout_ref: stdoutRef, stderr_ref: stderrRef, executed_at: new Date().toISOString() };
|
|
29
|
+
});
|
|
30
|
+
const passed = results.every((item) => item.exit_code === 0);
|
|
31
|
+
const report = { schema_version: 1, kind: "frontend-scaffold-verification", status: passed ? "passed" : "failed", project_root: projectRoot, scaffold_manifest_ref: manifestPath, commands: results };
|
|
32
|
+
const reportPath = path.join(evidenceDir, "scaffold-verification.json");
|
|
33
|
+
writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`);
|
|
34
|
+
if (passed) { manifest.completion_level = "empty-scaffold-verified"; manifest.scaffold_verification_ref = reportPath; writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`); }
|
|
35
|
+
return report;
|
|
36
|
+
}
|
|
37
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
38
|
+
try { const args = argsOf(process.argv.slice(2)); const report = verify(args["project-root"], args["evidence-dir"], { timeoutMs: Number(args["timeout-ms"] || 0) }); process.stdout.write(`${report.status}\n`); if (report.status !== "passed") process.exitCode = 1; }
|
|
39
|
+
catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
40
|
+
}
|
package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
|
|
8
|
+
const root = mkdtempSync(path.join(os.tmpdir(), "yss-frontend-scaffold-"));
|
|
9
|
+
process.on("exit", () => rmSync(root, { recursive: true, force: true }));
|
|
10
|
+
const template = path.join(root, "template"), output = path.join(root, "output"), evidence = path.join(root, "evidence"), bin = path.join(root, "bin");
|
|
11
|
+
mkdirSync(template); mkdirSync(bin);
|
|
12
|
+
writeFileSync(path.join(template, "package.json"), JSON.stringify({ name: "__APP_NAME__", scripts: { lint: "noop", "type-check": "noop", build: "noop" } }));
|
|
13
|
+
writeFileSync(path.join(template, "pnpm-lock.yaml"), "lockfileVersion: '9.0'\n");
|
|
14
|
+
writeFileSync(path.join(template, "micro-config.json"), JSON.stringify({ name: "__MICROAPP_NAME__", route: "__BASE_ROUTE__" }));
|
|
15
|
+
mkdirSync(path.join(template, "assets"));
|
|
16
|
+
writeFileSync(path.join(template, "assets/binary.bin"), Buffer.from([0, 255, 95, 95, 65, 80, 80, 95, 78, 65, 77, 69, 95, 95]));
|
|
17
|
+
writeFileSync(path.join(template, "assets/large.txt"), "__APP_NAME__".repeat(200_000));
|
|
18
|
+
writeFileSync(path.join(template, "assets/run.sh"), "#!/bin/sh\necho __APP_NAME__\n");
|
|
19
|
+
chmodSync(path.join(template, "assets/run.sh"), 0o755);
|
|
20
|
+
symlinkSync("run.sh", path.join(template, "assets/current"));
|
|
21
|
+
for (const args of [["init"], ["config", "user.email", "test@example.com"], ["config", "user.name", "test"], ["remote", "add", "origin", template], ["add", "."], ["commit", "-m", "fixture"]]) {
|
|
22
|
+
const result = spawnSync("git", args, { cwd: template, encoding: "utf8" }); assert.equal(result.status, 0, result.stderr);
|
|
23
|
+
}
|
|
24
|
+
const commit = spawnSync("git", ["rev-parse", "HEAD"], { cwd: template, encoding: "utf8" }).stdout.trim();
|
|
25
|
+
mkdirSync(path.join(template, "node_modules"));
|
|
26
|
+
writeFileSync(path.join(template, "node_modules/cache.txt"), "not approved");
|
|
27
|
+
writeFileSync(path.join(template, "micro-config.json"), "uncommitted edit");
|
|
28
|
+
const contract = {
|
|
29
|
+
schema_version: 4, kind: "project-scaffold-contract", contract_id: "frontend.demo.v1", contract_version: "1", status: "approved", persisted_ref: "docs/.scratch/demo/scaffold-contract.json", current_version: true,
|
|
30
|
+
delivery_role: "frontend", scaffold_kind: "frontend-yss-vue3", generator_skill: "yss-frontend-scaffold-generator", implementation_repository: output, target_output_dir: output, repository_scope: "external-repository", init_git: false,
|
|
31
|
+
frontend: { app_name: "demo-app", microapp_name: "demo", base_route: "/demo", package_manager: "pnpm", template: { repository: template, commit }, openapi_impact: "not-applicable", openapi_not_applicable_reason: "static-only" },
|
|
32
|
+
allowed_write_paths: [output], expected_evidence_files: [".yss/scaffold-generation.json"], verification_commands: ["pnpm install --frozen-lockfile", "pnpm lint", "pnpm type-check", "pnpm build"], approval: { approval_ref: "decision://frontend", approver: "user" }, generation_policy: { mode: "initialize-only", existing_target: "unsupported", old_project_migration: "unsupported", template_upgrade: "unsupported" }
|
|
33
|
+
};
|
|
34
|
+
const contractFile = path.join(root, "contract.json"); writeFileSync(contractFile, JSON.stringify(contract));
|
|
35
|
+
const mockPnpm = path.join(bin, "pnpm"); writeFileSync(mockPnpm, "#!/bin/sh\nexit 0\n"); chmodSync(mockPnpm, 0o755);
|
|
36
|
+
const runner = path.resolve(".agents/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs");
|
|
37
|
+
const result = spawnSync(process.execPath, [runner, "--contract-file", contractFile, "--template-checkout", template, "--output-dir", output, "--evidence-dir", evidence], { encoding: "utf8", env: { ...process.env, PATH: `${bin}:${process.env.PATH}` } });
|
|
38
|
+
assert.equal(result.status, 0, result.stderr);
|
|
39
|
+
assert.equal(existsSync(path.join(output, ".git")), false);
|
|
40
|
+
assert.equal(JSON.parse(readFileSync(path.join(output, "package.json"))).name, "demo-app");
|
|
41
|
+
assert.equal(JSON.parse(readFileSync(path.join(output, ".yss", "scaffold-generation.json"))).completion_level, "empty-scaffold-verified");
|
|
42
|
+
assert.equal(JSON.parse(readFileSync(path.join(evidence, "scaffold-verification.json"))).commands.length, 4);
|
|
43
|
+
assert.equal(existsSync(path.join(output, "node_modules")), false);
|
|
44
|
+
assert.equal(JSON.parse(readFileSync(path.join(output, "micro-config.json"))).name, "demo");
|
|
45
|
+
assert.deepEqual(readFileSync(path.join(output, "assets/binary.bin")), readFileSync(path.join(template, "assets/binary.bin")));
|
|
46
|
+
assert.deepEqual(readFileSync(path.join(output, "assets/large.txt")), readFileSync(path.join(template, "assets/large.txt")));
|
|
47
|
+
assert.equal(readlinkSync(path.join(output, "assets/current")), "run.sh");
|
|
48
|
+
assert.equal(statSync(path.join(output, "assets/run.sh")).mode & 0o777, 0o755);
|
|
49
|
+
assert.match(readFileSync(path.join(output, "assets/current"), "utf8"), /echo demo-app/);
|
|
50
|
+
const generated = JSON.parse(readFileSync(path.join(output, ".yss/scaffold-generation.json"))).generated_files;
|
|
51
|
+
assert.deepEqual(generated, ["assets/binary.bin", "assets/current", "assets/large.txt", "assets/run.sh", "micro-config.json", "package.json", "pnpm-lock.yaml"]);
|
|
52
|
+
const second = spawnSync(process.execPath, [runner, "--contract-file", contractFile, "--template-checkout", template, "--output-dir", output, "--evidence-dir", evidence], { encoding: "utf8", env: { ...process.env, PATH: `${bin}:${process.env.PATH}` } });
|
|
53
|
+
assert.notEqual(second.status, 0);
|
|
54
|
+
assert.match(second.stderr, /must not exist or must be empty/);
|
|
55
|
+
process.stdout.write("前端脚手架受控生成场景验证通过\n");
|
|
@@ -39,7 +39,7 @@ description: Use when a YSS vertical slice is entering implementation, spans mul
|
|
|
39
39
|
- Harness 内实现路径必须落在 `apps/backend/<project>/` 或 `apps/frontend/<project>/` 的具体项目目录;`apps/backend/`、`apps/frontend/` 只能作为容器,`app/backend/`、`app/frontend/` 及其子路径一律阻断。外部实现仓库使用其登记的真实项目根路径。`git-submodule` 使用 `implementation_path_policy: git-submodule-harness-apps`,空 gitlink、detached HEAD 或 `--force` 覆盖挂载点不得脚手架;`inspectWorkingTreeScope.writable` 必须为显式布尔值。
|
|
40
40
|
- 当前用户、缓存、审计、Excel、分布式 ID、请求校验、错误映射、加解密或网关韧性命中时,必须按 `compiler-contract.yaml` 的 `impact_to_capabilities` 补齐入口 capability;不能只在 `boundaries.md` 中提及。仅复用已经验证的平台认证 / 授权能力不算 component impact,不自动增加权限专项 skill。
|
|
41
41
|
- 业务行为使用 `behavior-tdd`;只有机械脚手架/生成物可用 `controlled-generation`,并记录例外和验证。
|
|
42
|
-
-
|
|
42
|
+
- 阶段 5 若命中交付面且无已有工程,按 Project Scaffold Contract schema v4 编译 `controlled-generation` 合同 draft。后端先读取 `scaffold-architecture-decisions.yaml`,只接受已达到 `lifecycle-approved` 且 digest 当前的 DDD / Layered MVC 选择;前端绑定标准模板精确 commit、应用标识、路由、OpenAPI 影响、目标路径和 `init_git` 决定。合同经生命周期批准并持久化后才能运行生成器。历史后端 schema v3 只读兼容并可完成已批准生成;前端只接受 v4。生成与验证完成、仓库登记并通过 `gate.implementation-repositories-ready` 后,才编译 Ticket 与业务 Slice Contract。
|
|
43
43
|
- 脚手架合同在编译阶段只能是 `draft` / `ready-for-lifecycle-review` / `blocked`;只有生命周期编排器可以把已持久化脚手架合同标记为 `approved`。脚手架合同只覆盖业务代码前的工程骨架工作单元;生成、基线校验和合同重编译完成后,它不能替代脚手架后的 Slice Implementation Contract。
|
|
44
44
|
- 脚手架输出消费批准的脚手架合同;脚手架后的所有生成后端代码都必须绑定当前批准且版本当前的 Slice Implementation Contract、主 YSS skill、依赖闭包、允许写路径、预期证据和 YSS Skill Execution Result。打印命令、`./mvnw validate` 单项通过或脚手架成功不能替代合同批准;生成范围从机械内容变成业务行为时触发完整重路由。
|
|
45
45
|
- 专项结果中的越界路径、缺失证据、`drift`、`violation` 或 `new_impacts` 必须阻断或重路由。
|
package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
| `component.gateway-resilience` | `yss-resilience4j` | `guidance`, `integration`, `slice-implementation`, `troubleshooting`, `component-maintenance`, `review-input` |
|
|
47
47
|
| `scaffold.ddd` | `yss-ddd-scaffold-generator` | `integration`, `component-maintenance` |
|
|
48
48
|
| `scaffold.layered-mvc` | `yss-layered-mvc-scaffold-generator` | `integration`, `component-maintenance` |
|
|
49
|
+
| `scaffold.frontend-vue3` | `yss-frontend-scaffold-generator` | `integration`, `component-maintenance` |
|
|
49
50
|
| `project-init.mvc-data-analysis` | `yss-mvc-data-analysis-project-initializer` | `component-maintenance` |
|
|
50
51
|
| `migration.springboot3` | `yss-up-springboot3` | `guidance`, `integration`, `troubleshooting`, `component-maintenance`, `review-input` |
|
|
51
52
|
|
|
@@ -73,6 +74,7 @@
|
|
|
73
74
|
| `backend.distributed-id` | `component.distributed-id` |
|
|
74
75
|
| `backend.ddd-scaffold` | `scaffold.ddd`, `quality.java-code-style` |
|
|
75
76
|
| `backend.mvc-scaffold` | `scaffold.layered-mvc`, `quality.java-code-style` |
|
|
77
|
+
| `frontend.vue3-scaffold` | `scaffold.frontend-vue3` |
|
|
76
78
|
| `backend.springboot3-migration` | `migration.springboot3`, `quality.java-code-style` |
|
|
77
79
|
|
|
78
80
|
## Impact Entry Mapping
|
|
@@ -103,6 +105,8 @@
|
|
|
103
105
|
|
|
104
106
|
| Skill | Dependency | Type | Condition |
|
|
105
107
|
| --- | --- | --- | --- |
|
|
108
|
+
| `code-review` | `yss-repository` | `context-conditional` | `backend-persistence-impact` |
|
|
109
|
+
| `code-review` | `yss-mybatis` | `context-conditional` | `backend-persistence-impact` |
|
|
106
110
|
| `yss-prototype-stage` | `prototype-review` | `review-only` | — |
|
|
107
111
|
| `yss-prototype-stage` | `yss-design-system` | `coordination-only` | — |
|
|
108
112
|
| `yss-prototype-stage` | `yss-antdv-next-design` | `context-conditional` | `h2-vue-antdv-next-default` |
|
|
@@ -138,8 +138,33 @@ context_plan:
|
|
|
138
138
|
context_stop_rule: minimal-sufficient-evidence
|
|
139
139
|
missing_context_action: [blocked, reroute]
|
|
140
140
|
|
|
141
|
+
project_scaffold_contract_schema:
|
|
142
|
+
schema_version: 4
|
|
143
|
+
schema_ref: docs/process/schemas/project-scaffold-contract.schema.json
|
|
144
|
+
identity: project-engineering-baseline
|
|
145
|
+
discriminant: delivery_role
|
|
146
|
+
delivery_roles:
|
|
147
|
+
backend:
|
|
148
|
+
scaffold_kinds: [backend-ddd, backend-layered-mvc]
|
|
149
|
+
generators: [yss-ddd-scaffold-generator, yss-layered-mvc-scaffold-generator]
|
|
150
|
+
requires: [scaffold_request_id, architecture_family, decision_ref, decision_id, decision_digest, project_name, base_package, maven_coordinates, profiles, module_profile]
|
|
151
|
+
frontend:
|
|
152
|
+
scaffold_kinds: [frontend-yss-vue3]
|
|
153
|
+
generators: [yss-frontend-scaffold-generator]
|
|
154
|
+
requires: [frontend, repository_scope, init_git]
|
|
155
|
+
openapi_modes: [frozen, not-applicable]
|
|
156
|
+
common_required: [contract_id, contract_version, status, persisted_ref, current_version, delivery_role, scaffold_kind, generator_skill, implementation_repository, target_output_dir, repository_scope, init_git, allowed_write_paths, expected_evidence_files, verification_commands, approval, generation_policy]
|
|
157
|
+
approved_by: yss-product-lifecycle
|
|
158
|
+
generation_mode: controlled-generation
|
|
159
|
+
target_policy: nonexistent-or-empty
|
|
160
|
+
force_overwrite: forbidden
|
|
161
|
+
compatibility:
|
|
162
|
+
backend_schema_v3: read-only-and-complete-approved-generation
|
|
163
|
+
frontend_before_v4: unsupported
|
|
164
|
+
|
|
141
165
|
scaffold_contract_schema:
|
|
142
166
|
schema_version: 3
|
|
167
|
+
compatibility_status: legacy-backend-read-only
|
|
143
168
|
identity: service-engineering-baseline
|
|
144
169
|
compiled_by: yss-implementation-contract-compiler
|
|
145
170
|
approved_by: yss-product-lifecycle
|
|
@@ -11,7 +11,7 @@ description: 用于在生命周期已批准的脚手架合同下生成通用 YSS
|
|
|
11
11
|
|
|
12
12
|
- backend `scaffold_status=required`,目标目录已确认且不存在。
|
|
13
13
|
- `scaffold-architecture-decisions.yaml` 中对应项目已达到 `lifecycle-approved`,确认架构为 `layered-mvc`。
|
|
14
|
-
- `yss-implementation-contract-compiler`
|
|
14
|
+
- `yss-implementation-contract-compiler` 已编译统一 Project Scaffold Contract schema v4;已批准且当前的后端 schema v3 可完成兼容生成。合同须由生命周期批准并持久化。
|
|
15
15
|
- 合同中的 `decision_id`、文件 digest、Profile、能力闭包、写路径和验证命令仍为当前版本。
|
|
16
16
|
|
|
17
17
|
任一条件缺失时返回 `blocked`。本生成器无交互、无默认回退;用户选择由 `yss-product-lifecycle` 在 `work-unit.technical-analysis` 的工程基线内完成。
|
|
@@ -55,7 +55,7 @@ node scripts/generate_and_verify_scaffold.mjs \
|
|
|
55
55
|
|
|
56
56
|
## 硬约束
|
|
57
57
|
|
|
58
|
-
-
|
|
58
|
+
- 接受统一 schema v4,兼容已批准后端 schema v3;验证器接受对应 Manifest v3/v4。历史 v2 只读兼容,不用于新生成。
|
|
59
59
|
- `architecture_family` 必须为 `layered-mvc`,`generator_skill` 必须为本 skill。
|
|
60
60
|
- 目标存在、`--force`、旧项目迁移、模板升级均为 `unsupported`。
|
|
61
61
|
- Harness 内只允许以 `apps/backend/` 为输出父容器;外部实现仓库使用已登记真实路径。
|