create-yss-spec 3.2.0 → 3.3.0
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 +1 -1
- 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/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 +1 -1
- 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 +107 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +41 -0
- package/template/.agents/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +37 -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 +48 -43
- package/template/.agents/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -2
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +67 -10
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +5 -1
- 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-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/.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/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 +1 -1
- 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 +107 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +41 -0
- package/template/.claude/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +37 -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 +48 -43
- package/template/.claude/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -2
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +67 -10
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration.md +5 -1
- 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-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/.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/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 +1 -1
- 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 +107 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +41 -0
- package/template/.codex/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +37 -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 +48 -43
- package/template/.codex/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -2
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +67 -10
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +5 -1
- 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-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/.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/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 +1 -1
- 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 +107 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +41 -0
- package/template/.cursor/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +37 -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 +48 -43
- package/template/.cursor/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +67 -10
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +5 -1
- 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-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/.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/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 +1 -1
- 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 +107 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +41 -0
- package/template/.pi/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +37 -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 +48 -43
- package/template/.pi/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -2
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +67 -10
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +5 -1
- 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-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/.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/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 +1 -1
- 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 +107 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +41 -0
- package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +37 -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 +48 -43
- package/template/.qoder/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -2
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +67 -10
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration.md +5 -1
- 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-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/.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/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 +1 -1
- 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 +107 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs +41 -0
- package/template/.trae/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs +37 -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 +48 -43
- package/template/.trae/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -2
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +67 -10
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration.md +5 -1
- 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-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/docs/agents/digital-human-roles.yaml +2 -0
- package/template/docs/agents/yss-skill-registry.yaml +5 -0
- package/template/docs/process/lifecycle-artifact-map.md +4 -0
- package/template/docs/process/lifecycle-registry-baseline.json +6 -1
- package/template/docs/process/lifecycle-registry.yaml +23 -0
- package/template/docs/process/schemas/implementation-repository-preparation-result.schema.json +38 -0
- package/template/docs/process/schemas/project-scaffold-contract.schema.json +113 -0
- package/template/docs/process/template-verification-profiles.yaml +23 -0
- package/template/docs/templates/implementation-repo-registry-template.md +8 -0
- package/template/docs/templates/review-report-template.md +7 -3
- package/template/scripts/lib/lifecycle-context-query.mjs +137 -0
- package/template/scripts/lib/lifecycle-transition.mjs +109 -3
- package/template/scripts/lib/scenario-checks.mjs +29 -26
- package/template/scripts/lib/skill-registry.mjs +9 -0
- package/template/scripts/query-lifecycle-context +25 -0
- package/template/scripts/verify-business-language-scenarios +0 -7
- package/template/scripts/verify-frontend-scaffold-generator-scenarios +2 -0
- package/template/scripts/verify-lifecycle-context-query-scenarios +68 -0
- package/template/scripts/verify-lifecycle-transition-scenarios +44 -4
- package/template/skills-lock.json +9 -9
- package/template.snapshot.json +4 -4
- 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/.qoder/skills/yss-ddd-scaffold-generator/scripts/run_scaffold_verification.mjs
CHANGED
|
@@ -39,7 +39,7 @@ function classifyFailure(phase, outcome) {
|
|
|
39
39
|
}
|
|
40
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; }
|
|
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] === "");
|
package/template/.qoder/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 复制工作树,排除模板 `.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,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { validateJsonSchema } from "../../../../scripts/lib/json-schema.mjs";
|
|
8
|
+
|
|
9
|
+
const fail = (message) => { throw new TypeError(message); };
|
|
10
|
+
const REPOSITORY_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../../..");
|
|
11
|
+
const sha256 = (value) => `sha256:${createHash("sha256").update(value).digest("hex")}`;
|
|
12
|
+
function argsOf(argv) {
|
|
13
|
+
const args = {};
|
|
14
|
+
for (let i = 0; i < argv.length; i += 2) args[argv[i].replace(/^--/, "")] = argv[i + 1];
|
|
15
|
+
return args;
|
|
16
|
+
}
|
|
17
|
+
function git(cwd, ...args) {
|
|
18
|
+
const result = spawnSync("git", args, { cwd, encoding: "utf8" });
|
|
19
|
+
if (result.status !== 0) fail(result.stderr || `git ${args.join(" ")} failed`);
|
|
20
|
+
return result.stdout.trim();
|
|
21
|
+
}
|
|
22
|
+
function walk(root) {
|
|
23
|
+
return readdirSync(root, { withFileTypes: true }).flatMap((entry) => {
|
|
24
|
+
const item = path.join(root, entry.name);
|
|
25
|
+
return entry.isDirectory() ? walk(item) : entry.isFile() ? [item] : [];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function validate(contract, outputDir) {
|
|
29
|
+
validateJsonSchema(contract, path.join(REPOSITORY_ROOT, "docs/process/schemas/project-scaffold-contract.schema.json"), { label: "Project Scaffold Contract v4" });
|
|
30
|
+
if (contract.schema_version !== 4 || contract.kind !== "project-scaffold-contract") fail("frontend scaffold requires Project Scaffold Contract schema v4");
|
|
31
|
+
if (contract.status !== "approved" || contract.current_version !== true || !contract.persisted_ref) fail("scaffold contract must be approved, persisted and current");
|
|
32
|
+
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");
|
|
33
|
+
if (path.resolve(contract.target_output_dir) !== outputDir) fail("output directory differs from approved contract");
|
|
34
|
+
if (contract.generation_policy?.mode !== "initialize-only" || contract.generation_policy?.existing_target !== "unsupported") fail("unsupported generation policy");
|
|
35
|
+
if (!contract.frontend?.template?.repository || !/^[a-f0-9]{40}$/.test(contract.frontend.template.commit || "")) fail("template repository and exact 40-character commit are required");
|
|
36
|
+
if (contract.frontend.openapi_impact === "frozen" && (!contract.frontend.openapi_json_ref || !contract.frontend.openapi_json_digest)) fail("frozen OpenAPI JSON and digest are required");
|
|
37
|
+
if (contract.frontend.openapi_impact === "not-applicable" && !contract.frontend.openapi_not_applicable_reason) fail("no-API scaffold requires a reason");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function generate({ contractFile, templateCheckout, outputDir }) {
|
|
41
|
+
const contract = JSON.parse(readFileSync(contractFile, "utf8"));
|
|
42
|
+
outputDir = path.resolve(outputDir);
|
|
43
|
+
templateCheckout = path.resolve(templateCheckout);
|
|
44
|
+
validate(contract, outputDir);
|
|
45
|
+
if (!existsSync(path.join(templateCheckout, ".git"))) fail("template checkout must be a Git worktree");
|
|
46
|
+
if (git(templateCheckout, "rev-parse", "HEAD") !== contract.frontend.template.commit) fail("template checkout does not match approved commit");
|
|
47
|
+
if (git(templateCheckout, "config", "--get", "remote.origin.url") !== contract.frontend.template.repository) fail("template repository differs from approved source");
|
|
48
|
+
if (existsSync(outputDir) && readdirSync(outputDir).length > 0) fail("target directory must not exist or must be empty");
|
|
49
|
+
mkdirSync(outputDir, { recursive: true });
|
|
50
|
+
cpSync(templateCheckout, outputDir, { recursive: true, filter: (source) => path.basename(source) !== ".git" });
|
|
51
|
+
|
|
52
|
+
const replacements = {
|
|
53
|
+
"__APP_NAME__": contract.frontend.app_name,
|
|
54
|
+
"__MICROAPP_NAME__": contract.frontend.microapp_name,
|
|
55
|
+
"__BASE_ROUTE__": contract.frontend.base_route,
|
|
56
|
+
...(contract.frontend.replacements || {}),
|
|
57
|
+
};
|
|
58
|
+
for (const file of walk(outputDir)) {
|
|
59
|
+
if (statSync(file).size > 2_000_000) continue;
|
|
60
|
+
let text;
|
|
61
|
+
try { text = readFileSync(file, "utf8"); } catch { continue; }
|
|
62
|
+
const replaced = Object.entries(replacements).reduce((value, [from, to]) => value.split(from).join(to), text);
|
|
63
|
+
if (replaced !== text) writeFileSync(file, replaced);
|
|
64
|
+
}
|
|
65
|
+
if (contract.frontend.openapi_impact === "frozen") {
|
|
66
|
+
const bytes = readFileSync(contract.frontend.openapi_json_ref);
|
|
67
|
+
if (sha256(bytes) !== contract.frontend.openapi_json_digest) fail("OpenAPI JSON digest mismatch");
|
|
68
|
+
mkdirSync(path.join(outputDir, "openapi"), { recursive: true });
|
|
69
|
+
writeFileSync(path.join(outputDir, "openapi", "openapi.json"), bytes);
|
|
70
|
+
}
|
|
71
|
+
if (contract.init_git === true) git(outputDir, "init");
|
|
72
|
+
const generatedFiles = walk(outputDir).map((file) => path.relative(outputDir, file)).filter((file) => file !== ".yss/scaffold-generation.json").sort();
|
|
73
|
+
const manifest = {
|
|
74
|
+
schema_version: 4,
|
|
75
|
+
kind: "frontend-scaffold",
|
|
76
|
+
delivery_role: "frontend",
|
|
77
|
+
generator_skill: "yss-frontend-scaffold-generator",
|
|
78
|
+
contract_id: contract.contract_id,
|
|
79
|
+
contract_version: contract.contract_version,
|
|
80
|
+
contract_digest: sha256(readFileSync(contractFile)),
|
|
81
|
+
contract_file_ref: path.resolve(contractFile),
|
|
82
|
+
persisted_ref: contract.persisted_ref,
|
|
83
|
+
approval_ref: contract.approval.approval_ref,
|
|
84
|
+
template: { ...contract.frontend.template, checkout: templateCheckout },
|
|
85
|
+
repository_scope: contract.repository_scope,
|
|
86
|
+
target_output_dir: outputDir,
|
|
87
|
+
init_git: contract.init_git,
|
|
88
|
+
openapi_impact: contract.frontend.openapi_impact,
|
|
89
|
+
generation_mode: "controlled-generation",
|
|
90
|
+
generation_policy: contract.generation_policy,
|
|
91
|
+
verification_commands: contract.verification_commands,
|
|
92
|
+
generated_files: generatedFiles,
|
|
93
|
+
completion_level: "generated",
|
|
94
|
+
generated_at: new Date().toISOString(),
|
|
95
|
+
};
|
|
96
|
+
mkdirSync(path.join(outputDir, ".yss"), { recursive: true });
|
|
97
|
+
writeFileSync(path.join(outputDir, ".yss", "scaffold-generation.json"), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
98
|
+
return manifest;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
102
|
+
try {
|
|
103
|
+
const args = argsOf(process.argv.slice(2));
|
|
104
|
+
generate({ contractFile: args["contract-file"], templateCheckout: args["template-checkout"], outputDir: args["output-dir"] });
|
|
105
|
+
process.stdout.write("frontend scaffold generated\n");
|
|
106
|
+
} catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
107
|
+
}
|
package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/run_scaffold_verification.mjs
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
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) {
|
|
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 result = spawnSync("pnpm", argv, { cwd: projectRoot, encoding: "utf8" });
|
|
27
|
+
const stdoutRef = path.join(evidenceDir, `${index + 1}-stdout.log`), stderrRef = path.join(evidenceDir, `${index + 1}-stderr.log`);
|
|
28
|
+
writeFileSync(stdoutRef, result.stdout || ""); writeFileSync(stderrRef, result.stderr || "");
|
|
29
|
+
return { command, exit_code: result.status ?? 1, duration_ms: Date.now() - started, stdout_ref: stdoutRef, stderr_ref: stderrRef, executed_at: new Date().toISOString() };
|
|
30
|
+
});
|
|
31
|
+
const passed = results.every((item) => item.exit_code === 0);
|
|
32
|
+
const report = { schema_version: 1, kind: "frontend-scaffold-verification", status: passed ? "passed" : "failed", project_root: projectRoot, scaffold_manifest_ref: manifestPath, commands: results };
|
|
33
|
+
const reportPath = path.join(evidenceDir, "scaffold-verification.json");
|
|
34
|
+
writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`);
|
|
35
|
+
if (passed) { manifest.completion_level = "empty-scaffold-verified"; manifest.scaffold_verification_ref = reportPath; writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`); }
|
|
36
|
+
return report;
|
|
37
|
+
}
|
|
38
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
39
|
+
try { const args = argsOf(process.argv.slice(2)); const report = verify(args["project-root"], args["evidence-dir"]); process.stdout.write(`${report.status}\n`); if (report.status !== "passed") process.exitCode = 1; }
|
|
40
|
+
catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
41
|
+
}
|
package/template/.qoder/skills/yss-frontend-scaffold-generator/scripts/scaffold-generator.test.mjs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, 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
|
+
for (const args of [["init"], ["config", "user.email", "test@example.com"], ["config", "user.name", "test"], ["remote", "add", "origin", template], ["add", "."], ["commit", "-m", "fixture"]]) {
|
|
16
|
+
const result = spawnSync("git", args, { cwd: template, encoding: "utf8" }); assert.equal(result.status, 0, result.stderr);
|
|
17
|
+
}
|
|
18
|
+
const commit = spawnSync("git", ["rev-parse", "HEAD"], { cwd: template, encoding: "utf8" }).stdout.trim();
|
|
19
|
+
const contract = {
|
|
20
|
+
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,
|
|
21
|
+
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,
|
|
22
|
+
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" },
|
|
23
|
+
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" }
|
|
24
|
+
};
|
|
25
|
+
const contractFile = path.join(root, "contract.json"); writeFileSync(contractFile, JSON.stringify(contract));
|
|
26
|
+
const mockPnpm = path.join(bin, "pnpm"); writeFileSync(mockPnpm, "#!/bin/sh\nexit 0\n"); chmodSync(mockPnpm, 0o755);
|
|
27
|
+
const runner = path.resolve(".agents/skills/yss-frontend-scaffold-generator/scripts/generate_and_verify_scaffold.mjs");
|
|
28
|
+
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}` } });
|
|
29
|
+
assert.equal(result.status, 0, result.stderr);
|
|
30
|
+
assert.equal(existsSync(path.join(output, ".git")), false);
|
|
31
|
+
assert.equal(JSON.parse(readFileSync(path.join(output, "package.json"))).name, "demo-app");
|
|
32
|
+
assert.equal(JSON.parse(readFileSync(path.join(output, ".yss", "scaffold-generation.json"))).completion_level, "empty-scaffold-verified");
|
|
33
|
+
assert.equal(JSON.parse(readFileSync(path.join(evidence, "scaffold-verification.json"))).commands.length, 4);
|
|
34
|
+
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}` } });
|
|
35
|
+
assert.notEqual(second.status, 0);
|
|
36
|
+
assert.match(second.stderr, /must not exist or must be empty/);
|
|
37
|
+
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/.qoder/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/` 为输出父容器;外部实现仓库使用已登记真实路径。
|
package/template/.qoder/skills/yss-layered-mvc-scaffold-generator/scripts/generate_scaffold.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
2
|
+
/** 依据生命周期批准的兼容 schema v3 或统一 schema v4 合同生成纯机械 YSS 分层 MVC 后端骨架。 */
|
|
3
3
|
import { assertScaffoldUserDecision } from "../../../../scripts/lib/user-decision.mjs";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { chmod, cp, lstat, mkdir, mkdtemp, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
|
|
@@ -10,6 +10,7 @@ import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
|
|
|
10
10
|
import { findGitRoot, gitSubmoduleScaffoldViolation, overlayMountViolation } from "../../../../scripts/lib/repository-scope-policy.mjs";
|
|
11
11
|
import { assertLocalDatabaseProfile, localDatabaseConfiguration, scaffoldArchitectureIdentity } from "../../../../scripts/lib/scaffold-local-database.mjs";
|
|
12
12
|
import { validateArchitectureIdentity } from "../../../../scripts/lib/backend-architecture.mjs";
|
|
13
|
+
import { validateJsonSchema } from "../../../../scripts/lib/json-schema.mjs";
|
|
13
14
|
|
|
14
15
|
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
15
16
|
const SKILL_ROOT = path.resolve(SCRIPT_DIR, "..");
|
|
@@ -151,11 +152,13 @@ async function validateContract(options, skillId, architectureProfile) {
|
|
|
151
152
|
const contractText = await readFile(contractFile, "utf8").catch(() => fail(`脚手架合同不可读取: ${contractFile}`));
|
|
152
153
|
let contract;
|
|
153
154
|
try { contract = JSON.parse(contractText); } catch { fail("脚手架合同必须是 JSON 对象"); }
|
|
154
|
-
if (contract.schema_version
|
|
155
|
+
if (![3, 4].includes(contract.schema_version)) fail(`unsupported: 只接受兼容 scaffold contract v3 或统一 v4,收到 v${contract.schema_version}`);
|
|
156
|
+
if (contract.schema_version === 4 && (contract.kind !== "project-scaffold-contract" || contract.delivery_role !== "backend" || contract.scaffold_kind !== "backend-layered-mvc")) fail("schema v4 合同必须绑定 backend/backend-layered-mvc");
|
|
157
|
+
if (contract.schema_version === 4) validateJsonSchema(contract, path.join(REPOSITORY_ROOT, "docs/process/schemas/project-scaffold-contract.schema.json"), { label: "Project Scaffold Contract v4" });
|
|
155
158
|
const required = ["contract_id", "contract_version", "scaffold_request_id", "status", "compiler_draft_ref", "lifecycle_approval_ref", "persisted_ref", "current_version", "implementation_repository", "backend_repository", "scaffold_status", "project_name", "target_output_dir", "base_package", "architecture_family", "generator_skill", "decision_ref", "decision_id", "decision_digest", "maven_coordinates", "profiles", "module_profile", "allowed_write_paths", "expected_evidence_files", "verification_commands", "approval", "work_unit", "generation_policy"];
|
|
156
159
|
const missing = required.filter((field) => !isPresent(contract[field]));
|
|
157
160
|
if (missing.length) fail(`脚手架合同缺少字段: ${missing.join(", ")}`);
|
|
158
|
-
if (contract.status !== "approved" || contract.current_version !== contract.contract_version) fail("脚手架合同必须已批准且为当前版本");
|
|
161
|
+
if (contract.status !== "approved" || (contract.current_version !== contract.contract_version && !(contract.schema_version === 4 && contract.current_version === true))) fail("脚手架合同必须已批准且为当前版本");
|
|
159
162
|
if (contract.contract_id !== options.contractId || contract.contract_version !== options.contractVersion || contract.compiler_draft_ref !== options.compilerDraftRef || contract.lifecycle_approval_ref !== options.approvalRef || contract.persisted_ref !== options.persistedRef) fail("命令行合同元数据与批准合同不一致");
|
|
160
163
|
if (contract.scaffold_status !== "required" || contract.architecture_family !== "layered-mvc" || contract.generator_skill !== skillId) fail("合同必须绑定 layered-mvc 与本生成器");
|
|
161
164
|
if (contract.project_name !== options.projectName || contract.base_package !== options.basePackage || path.resolve(contract.target_output_dir) !== path.resolve(options.outputDir)) fail("项目身份或输出目录与合同不一致");
|
|
@@ -244,14 +247,14 @@ export async function generate(options, { skillId = SKILL_ID, architectureProfil
|
|
|
244
247
|
await cp(wrapper, projectRoot, { recursive: true });
|
|
245
248
|
await chmod(path.join(projectRoot, "mvnw"), 0o755);
|
|
246
249
|
if (finalize) await finalize({ projectRoot, contract, architectureIdentity: scaffoldArchitectureIdentity(contract, sha256(contractText)) });
|
|
247
|
-
await put(projectRoot, "README.md", `# ${options.projectName}\n\n该工程由 ${skillId} 根据批准的 schema
|
|
250
|
+
await put(projectRoot, "README.md", `# ${options.projectName}\n\n该工程由 ${skillId} 根据批准的 schema v${contract.schema_version} 合同生成。模块:${modules.join("、")}。不包含业务 API、SQL 或生产数据库绑定。\n\n本地运行需同时显式启用 Maven -Pscaffold-local 和 Spring scaffold-local Profile;测试独立使用 H2。生产数据库须由后续已批准存储工作单元接入。`);
|
|
248
251
|
const generatedFiles = [];
|
|
249
252
|
for (const entry of await fileEntries(projectRoot, new Set([".yss/scaffold-generation.json"]))) generatedFiles.push({ path: entry.relative, owner: "generator", sha256: rawSha256(await readFile(entry.target)) });
|
|
250
253
|
const architectureRuleset = `${serverRoot}/src/test/java/${packagePath}/architecture/LayeredMvcArchitectureTest.java`;
|
|
251
254
|
const downstream = {};
|
|
252
255
|
for (const skill of ["yss-application", "yss-repository", "yss-mybatis", "yss-web-controller", "yss-dto", "yss-exception", "yss-validation", "mapstruct", "lombok", "alibaba-java-code-style"]) downstream[skill] = (await treeDigest(path.join(REPOSITORY_ROOT, ".agents/skills", skill))).replace(/^sha256:/, "");
|
|
253
256
|
const manifest = {
|
|
254
|
-
schema_version:
|
|
257
|
+
schema_version: contract.schema_version,
|
|
255
258
|
kind: architectureProfile === "mvc-data-analysis-v1" ? "service-project-initialization" : "backend-scaffold",
|
|
256
259
|
architecture_profile: contract.architecture_profile,
|
|
257
260
|
architecture_identity: scaffoldArchitectureIdentity(contract, sha256(contractText)),
|
|
@@ -18,7 +18,7 @@ const capabilityModules = {
|
|
|
18
18
|
combined: { capabilities: ["external-integration", "feign-client"], modules: ["server", "service", "repository", "adapter", "client", "feign-client"] }
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
async function fixture(t, { profile = capabilityModules.basic, architectureProfile = "layered-mvc-service", skillId = "yss-layered-mvc-scaffold-generator" } = {}) {
|
|
21
|
+
async function fixture(t, { profile = capabilityModules.basic, architectureProfile = "layered-mvc-service", skillId = "yss-layered-mvc-scaffold-generator", schemaVersion = 3 } = {}) {
|
|
22
22
|
const root = await mkdtemp(path.join(os.tmpdir(), "yss-layered-mvc-"));
|
|
23
23
|
t.after(() => rm(root, { recursive: true, force: true }));
|
|
24
24
|
const output = path.join(root, "backend");
|
|
@@ -30,7 +30,12 @@ async function fixture(t, { profile = capabilityModules.basic, architectureProfi
|
|
|
30
30
|
const decisionFile = path.join(root, "scaffold-architecture-decisions.yaml");
|
|
31
31
|
await writeFile(decisionFile, decisionText);
|
|
32
32
|
const contract = {
|
|
33
|
-
schema_version:
|
|
33
|
+
schema_version: schemaVersion,
|
|
34
|
+
kind: "project-scaffold-contract",
|
|
35
|
+
delivery_role: "backend",
|
|
36
|
+
scaffold_kind: "backend-layered-mvc",
|
|
37
|
+
repository_scope: "external-repository",
|
|
38
|
+
init_git: false,
|
|
34
39
|
contract_id: "scaffold.demo-service.v1",
|
|
35
40
|
contract_version: 1,
|
|
36
41
|
scaffold_request_id: "request.demo-service",
|
|
@@ -97,6 +102,16 @@ test("旧数据库和 Mock 参数在写入前被拒绝", async (t) => {
|
|
|
97
102
|
}
|
|
98
103
|
});
|
|
99
104
|
|
|
105
|
+
test("统一 Project Scaffold Contract v4 可生成 Layered MVC 后端并保留 v4 Manifest", async (t) => {
|
|
106
|
+
const data = await fixture(t, { schemaVersion: 4 });
|
|
107
|
+
data.contract.current_version = true;
|
|
108
|
+
await writeFile(data.contractFile, JSON.stringify(data.contract));
|
|
109
|
+
const result = spawnSync(process.execPath, [script, ...data.args], { encoding: "utf8" });
|
|
110
|
+
assert.equal(result.status, 0, result.stderr);
|
|
111
|
+
const manifest = JSON.parse(await readFile(path.join(data.project, ".yss/scaffold-generation.json"), "utf8"));
|
|
112
|
+
assert.equal(manifest.schema_version, 4);
|
|
113
|
+
});
|
|
114
|
+
|
|
100
115
|
test("可选离线 Maven 可行性检查(不替代受控仓库验收)", { skip: process.env.YSS_BACKEND_OFFLINE_PROBE !== "1" }, async (t) => {
|
|
101
116
|
const data = await fixture(t);
|
|
102
117
|
const generated = spawnSync(process.execPath, [script, ...data.args], { encoding: "utf8" });
|
|
@@ -1,77 +1,53 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yss-mybatis
|
|
3
|
-
description: 用于 YSS MyBatis
|
|
3
|
+
description: 用于 YSS MyBatis / MyBatis-Plus 组件能力核验、接入决策和排障;涉及 Mapper/Repository 基类、分页、批量 SQL、扫描配置或数据源能力时使用,不负责生成持久层结构。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# yss-mybatis
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
本 Skill 只维护 `yss-component-persistence` 的组件能力、选择条件和排障顺序。PO、Repository、Convertor、Gateway/Query Adapter 的结构与生成边界由 `yss-repository` 负责。
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## 入口与前置
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
12
|
+
1. 读取批准且当前的 `architecture_identity`、`persistence_profile`、实现仓登记和 Slice Implementation Contract。没有合同的故障诊断可以继续,但不得据此生成或改变架构。
|
|
13
|
+
2. 精确类名、方法签名、配置 key、默认值或启用条件必须先读 [source-index.md](references/source-index.md),并按 `yss-skill-source-index-refresh/references/source-location.md` 核验组件 tree 与组件子树 clean 状态。
|
|
14
|
+
3. 组件 tree 不匹配或 persistence 子树为 dirty 时,路径提示只能用于定位;精确实现或审查结论返回 `stale` / `missing_evidence`,刷新索引后再继续。
|
|
15
|
+
4. 新 DDD / MVC scaffold 只支持批准的 `mybatis-plus` Profile。普通 MyBatis 仅用于既有工程维护、兼容与排障;新增支持必须有独立 Profile 和 fixture,不自动猜测或混用。
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 稳定决策规则
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
- 基类、Mapper 注解、XML 位置和扫描范围以批准 Profile、当前工程基线及当前组件源码共同决定;不得在既有体系外再造 Mapper 抽象。
|
|
20
|
+
- 一条查询 seam 只能有一个分页责任模型。核对实际插件/切面开关、拦截范围、参数绑定条件和返回 total 的责任,不以“依赖已引入”代替行为验证。
|
|
21
|
+
- 批量写入必须证明是组件当前支持的 SQL 级批量能力,并验证分批大小、字段填充、主键和数据库方言;循环单条写入不能冒充批量 SQL。
|
|
22
|
+
- 多数据源实例创建不等于动态路由、线程上下文切换或事务传播。先做 capability check;组件未提供的路由能力必须由批准的上层适配承担。
|
|
23
|
+
- Mapper/XML、逻辑删除、审计字段、主键策略、动态排序/分组白名单和参数绑定必须与数据合同一致;任何 SQL/DDL/索引新影响返回 `new_impacts`。
|
|
24
|
+
- 事务边界归批准的 Application 用例或 MVC service/core;Repository 不临时声明新的业务事务。
|
|
23
25
|
|
|
24
|
-
##
|
|
26
|
+
## 任务分流
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
## 实施建议
|
|
33
|
-
|
|
34
|
-
- 通用模式优先继承 `BaseRepository`
|
|
35
|
-
- MP 模式优先继承项目既有的 `BasePlusRepository`
|
|
36
|
-
- 批量导入优先使用真正的 SQL 级批量方法,不要默认循环单条插入
|
|
37
|
-
- 多数据源问题优先先看配置和扫描范围,再怀疑业务代码
|
|
38
|
-
- DDD 分页经 Application Query Port 进入 Infrastructure;MVC 经 service/core 进入 Repository。不把 `PageQuery` 带入 Domain Gateway,也不得在 Repository 内临时发明分页参数。
|
|
39
|
-
- 生成或重构持久层时,先看当前模块已有 Repository/Mapper 命名、包路径、XML 位置。
|
|
40
|
-
|
|
41
|
-
## 检查清单
|
|
42
|
-
|
|
43
|
-
- Mapper 扫描路径是否正确。
|
|
44
|
-
- XML 路径和接口是否对齐。
|
|
45
|
-
- `PageQuery` 是否真的出现在被拦截的方法参数里。
|
|
46
|
-
- 批量方法是否用了项目推荐实现。
|
|
47
|
-
- 多数据源名称和主从配置是否一致。
|
|
48
|
-
- MyBatis 与 MyBatis-Plus 的基类、分页插件和扫描配置是否混用。
|
|
49
|
-
- 数据源切换是否在事务边界之前完成。
|
|
28
|
+
| 请求 | 本 Skill 动作 | 后续路由 |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| 组件接入、基类选择、配置核验 | 读取当前 Profile 和源码能力矩阵,给出来源可追踪的选择 | 需要结构实现时转 `yss-repository` |
|
|
31
|
+
| 分页、批量、扫描、XML、数据源故障 | 按下列顺序定位并保留实际证据 | 发现合同或数据影响时返回编译器 |
|
|
32
|
+
| 生成 PO / Repository / Convertor / GatewayImpl | 不生成 | `yss-repository` |
|
|
33
|
+
| 普通 MyBatis 新工程生成 | `unsupported` | 新 Profile / fixture 获批后再进入 |
|
|
50
34
|
|
|
51
35
|
## 排障顺序
|
|
52
36
|
|
|
53
|
-
1.
|
|
54
|
-
2.
|
|
55
|
-
3.
|
|
56
|
-
4.
|
|
57
|
-
5.
|
|
58
|
-
6.
|
|
59
|
-
|
|
60
|
-
## 修改约束
|
|
61
|
-
|
|
62
|
-
- 不要同时引入两套分页机制而不说明谁生效。
|
|
63
|
-
- 不要在已有 Repository 基类体系之外再造一套 Mapper 抽象。
|
|
64
|
-
- 若用户只是要生成持久层骨架,优先衔接 `yss-repository`。
|
|
37
|
+
1. 依赖与 Profile:starter、组件版本、MyBatis/MyBatis-Plus 模式是否与合同一致。
|
|
38
|
+
2. 装配与开关:自动配置、条件属性、Mapper 扫描和 XML location 是否真实生效。
|
|
39
|
+
3. 调用 seam:代理是否命中、分页参数位置/类型、分页插件链和 total 回填责任。
|
|
40
|
+
4. 映射:接口签名、XML namespace、resultMap、字段、逻辑删除和主键策略。
|
|
41
|
+
5. 批量:是否调用当前公开批量入口、分批与方言是否匹配、是否退化为循环单条。
|
|
42
|
+
6. 数据源:先确认组件只提供了什么,再检查上层路由与事务进入顺序;不得假设存在当前线程数据源上下文。
|
|
43
|
+
7. 最后检查 SQL、绑定参数、数据库方言与执行计划。
|
|
65
44
|
|
|
66
|
-
##
|
|
45
|
+
## Review 输入
|
|
67
46
|
|
|
68
|
-
-
|
|
69
|
-
- 基础 Repository:`assets/BaseRepository.java`
|
|
70
|
-
- 分页切面:`assets/EntityQueryAspect.java`
|
|
71
|
-
- MyBatis 基础配置:`assets/MybatisBaseConfiguration.java`
|
|
47
|
+
仅审查本体项目和合同/实现仓登记的后端研发项目。命中 Mapper、Repository、SQL、分页、批量、扫描配置或数据源能力时,`code-review` Standards 轴必须读取本 Skill 和当前 source index;无持久化影响时显式记录带原因的 `not-applicable`。
|
|
72
48
|
|
|
73
|
-
##
|
|
49
|
+
## 结果与验证
|
|
74
50
|
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
51
|
+
- 行为变更使用 `behavior-tdd`;纯 Mapper/XML 骨架仅在批准合同明确为 `controlled-generation` 时允许。
|
|
52
|
+
- 使用项目根 `./mvnw ...` 记录实际命令、退出码和时间;H2 只证明本地/测试行为,不证明生产方言。
|
|
53
|
+
- 按 [YSS Skill Execution Result v2](../yss-implementation-contract-compiler/references/yss-skill-execution-result.md) 返回证据、`seam_deferred`、`deviations`、`new_impacts`、`drift` 和 `violation`。
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
version: 1
|
|
2
2
|
interface:
|
|
3
3
|
display_name: "YSS MyBatis"
|
|
4
|
-
short_description: "MyBatis
|
|
5
|
-
default_prompt: "Use $yss-mybatis to
|
|
4
|
+
short_description: "MyBatis 组件能力、配置、分页、批量与数据源排障"
|
|
5
|
+
default_prompt: "Use $yss-mybatis to verify or troubleshoot current YSS MyBatis capabilities and configuration; route persistence structure work to $yss-repository."
|