create-yss-spec 3.1.0 → 3.2.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 +119 -89
- package/bin/create-yss-spec.js +11 -3
- package/package.json +9 -2
- package/src/api/_sync-service.js +191 -0
- package/src/api/index.js +22 -0
- package/src/api/project-diff.js +9 -0
- package/src/api/project-doctor.js +10 -0
- package/src/api/template-apply.js +10 -0
- package/src/api/template-plan.js +9 -0
- package/src/cli/args.js +60 -0
- package/src/cli/error-output.js +52 -0
- package/src/cli/flags.js +9 -0
- package/src/cli/help.js +95 -0
- package/src/cli/index.js +82 -0
- package/src/cli/plan-output.js +61 -0
- package/src/cli/prompts.js +91 -0
- package/src/cli/router.js +41 -0
- package/src/cli.js +5 -2253
- package/src/commands/attach.js +280 -0
- package/src/commands/diff.js +23 -0
- package/src/commands/doctor.js +417 -0
- package/src/commands/init.js +193 -0
- package/src/commands/sync.js +146 -0
- package/src/commands/update.js +14 -0
- package/src/contracts/apply-result-v1.json +45 -0
- package/src/contracts/customization-policy-v1.json +28 -0
- package/src/contracts/doctor-report-v1.json +29 -0
- package/src/contracts/error-envelope-v1.json +24 -0
- package/src/contracts/generator-policy-v1.json +24 -0
- package/src/contracts/ownership-policy-v1.json +40 -0
- package/src/contracts/plan-schema-v1.json +115 -0
- package/src/family-identity.js +365 -0
- package/src/family-runtime.js +23 -0
- package/src/filesystem/apply-plan.js +44 -0
- package/src/filesystem/copy-path.js +28 -0
- package/src/filesystem/path-utils.js +67 -0
- package/src/filesystem/transaction-runner.js +41 -0
- package/src/filesystem/transaction.js +153 -0
- package/src/git/submodule.js +115 -0
- package/src/git/worktree.js +69 -0
- package/src/template/attach-planner-runtime.js +51 -0
- package/src/template/attach-planner.js +160 -0
- package/src/template/instance-runtime.js +463 -0
- package/src/template/lifecycle-metadata.js +99 -0
- package/src/template/lifecycle-policy.js +129 -0
- package/src/template/lifecycle-runtime.js +90 -0
- package/src/template/migration-planner.js +95 -0
- package/src/template/migration-runtime.js +247 -0
- package/src/template/ownership-metadata.js +79 -0
- package/src/template/ownership-policy.js +149 -0
- package/src/template/ownership-runtime.js +109 -0
- package/src/template/plan-schema.js +36 -0
- package/src/template/sync-planner-runtime.js +57 -0
- package/src/template/sync-planner.js +206 -0
- package/src/template/verification-runtime.js +154 -0
- package/src/validation/identity.js +41 -0
- package/src/validation/metadata.js +105 -0
- package/src/validation/security.js +67 -0
- package/src/validation/snapshot.js +47 -0
- package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
- package/template/.agents/skills/yss-domain/SKILL.md +3 -3
- package/template/.agents/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +4 -2
- package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +5 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -2
- package/template/.agents/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +10 -1
- package/template/.agents/skills/yss-mvc-design/SKILL.md +16 -0
- package/template/.agents/skills/yss-mvc-design/agents/openai.yaml +4 -0
- package/template/.agents/skills/yss-mvc-design/references/mvc-design.schema.json +315 -0
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +4 -2
- package/template/.agents/skills/yss-product-lifecycle/references/artifact-dependencies.md +2 -2
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +14 -9
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +1 -1
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.agents/skills/yss-tactical-design/SKILL.md +2 -2
- package/template/.agents/skills/yss-tactical-design/references/output-template.md +2 -0
- package/template/.agents/skills/yss-tactical-design/references/tactical-design-contract.md +3 -1
- package/template/.agents/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +3 -2
- package/template/.agents/skills/yss-technical-design/SKILL.md +31 -0
- package/template/.agents/skills/yss-technical-design/agents/openai.yaml +4 -0
- package/template/.agents/skills/yss-technical-design/references/technical-design-common.schema.json +290 -0
- package/template/.agents/skills/yss-technical-design/references/technical-design-contract.md +31 -0
- package/template/.agents/skills/yss-technical-design/references/technical-design.schema.json +759 -0
- package/template/.agents/skills/yss-technical-design/scripts/generate-schema.mjs +20 -0
- package/template/.agents/skills/yss-technical-design/scripts/validate-technical-design.mjs +134 -0
- package/template/.agents/skills/yss-technical-design/tests/fixtures.mjs +32 -0
- package/template/.agents/skills/yss-technical-design/tests/run-scenarios.mjs +82 -0
- package/template/.agents/skills/yss-ui/SKILL.md +2 -0
- package/template/.claude/skills/yss-domain/SKILL.md +3 -3
- package/template/.claude/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
- package/template/.claude/skills/yss-implementation-contract-compiler/SKILL.md +4 -2
- package/template/.claude/skills/yss-implementation-contract-compiler/references/boundaries.md +5 -0
- package/template/.claude/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -2
- package/template/.claude/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +10 -1
- package/template/.claude/skills/yss-mvc-design/SKILL.md +16 -0
- package/template/.claude/skills/yss-mvc-design/agents/openai.yaml +4 -0
- package/template/.claude/skills/yss-mvc-design/references/mvc-design.schema.json +315 -0
- package/template/.claude/skills/yss-product-lifecycle/SKILL.md +4 -2
- package/template/.claude/skills/yss-product-lifecycle/references/artifact-dependencies.md +2 -2
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +14 -9
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration.md +1 -1
- package/template/.claude/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.claude/skills/yss-tactical-design/SKILL.md +2 -2
- package/template/.claude/skills/yss-tactical-design/references/output-template.md +2 -0
- package/template/.claude/skills/yss-tactical-design/references/tactical-design-contract.md +3 -1
- package/template/.claude/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +3 -2
- package/template/.claude/skills/yss-technical-design/SKILL.md +31 -0
- package/template/.claude/skills/yss-technical-design/agents/openai.yaml +4 -0
- package/template/.claude/skills/yss-technical-design/references/technical-design-common.schema.json +290 -0
- package/template/.claude/skills/yss-technical-design/references/technical-design-contract.md +31 -0
- package/template/.claude/skills/yss-technical-design/references/technical-design.schema.json +759 -0
- package/template/.claude/skills/yss-technical-design/scripts/generate-schema.mjs +20 -0
- package/template/.claude/skills/yss-technical-design/scripts/validate-technical-design.mjs +134 -0
- package/template/.claude/skills/yss-technical-design/tests/fixtures.mjs +32 -0
- package/template/.claude/skills/yss-technical-design/tests/run-scenarios.mjs +82 -0
- package/template/.claude/skills/yss-ui/SKILL.md +2 -0
- package/template/.codex/skills/yss-domain/SKILL.md +3 -3
- package/template/.codex/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +4 -2
- package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +5 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -2
- package/template/.codex/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +10 -1
- package/template/.codex/skills/yss-mvc-design/SKILL.md +16 -0
- package/template/.codex/skills/yss-mvc-design/agents/openai.yaml +4 -0
- package/template/.codex/skills/yss-mvc-design/references/mvc-design.schema.json +315 -0
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +4 -2
- package/template/.codex/skills/yss-product-lifecycle/references/artifact-dependencies.md +2 -2
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +14 -9
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +1 -1
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.codex/skills/yss-tactical-design/SKILL.md +2 -2
- package/template/.codex/skills/yss-tactical-design/references/output-template.md +2 -0
- package/template/.codex/skills/yss-tactical-design/references/tactical-design-contract.md +3 -1
- package/template/.codex/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +3 -2
- package/template/.codex/skills/yss-technical-design/SKILL.md +31 -0
- package/template/.codex/skills/yss-technical-design/agents/openai.yaml +4 -0
- package/template/.codex/skills/yss-technical-design/references/technical-design-common.schema.json +290 -0
- package/template/.codex/skills/yss-technical-design/references/technical-design-contract.md +31 -0
- package/template/.codex/skills/yss-technical-design/references/technical-design.schema.json +759 -0
- package/template/.codex/skills/yss-technical-design/scripts/generate-schema.mjs +20 -0
- package/template/.codex/skills/yss-technical-design/scripts/validate-technical-design.mjs +134 -0
- package/template/.codex/skills/yss-technical-design/tests/fixtures.mjs +32 -0
- package/template/.codex/skills/yss-technical-design/tests/run-scenarios.mjs +82 -0
- package/template/.codex/skills/yss-ui/SKILL.md +2 -0
- package/template/.cursor/skills/yss-domain/SKILL.md +3 -3
- package/template/.cursor/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +4 -2
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +5 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -2
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +10 -1
- package/template/.cursor/skills/yss-mvc-design/SKILL.md +16 -0
- package/template/.cursor/skills/yss-mvc-design/agents/openai.yaml +4 -0
- package/template/.cursor/skills/yss-mvc-design/references/mvc-design.schema.json +315 -0
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +4 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/artifact-dependencies.md +2 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +14 -9
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +1 -1
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.cursor/skills/yss-tactical-design/SKILL.md +2 -2
- package/template/.cursor/skills/yss-tactical-design/references/output-template.md +2 -0
- package/template/.cursor/skills/yss-tactical-design/references/tactical-design-contract.md +3 -1
- package/template/.cursor/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +3 -2
- package/template/.cursor/skills/yss-technical-design/SKILL.md +31 -0
- package/template/.cursor/skills/yss-technical-design/agents/openai.yaml +4 -0
- package/template/.cursor/skills/yss-technical-design/references/technical-design-common.schema.json +290 -0
- package/template/.cursor/skills/yss-technical-design/references/technical-design-contract.md +31 -0
- package/template/.cursor/skills/yss-technical-design/references/technical-design.schema.json +759 -0
- package/template/.cursor/skills/yss-technical-design/scripts/generate-schema.mjs +20 -0
- package/template/.cursor/skills/yss-technical-design/scripts/validate-technical-design.mjs +134 -0
- package/template/.cursor/skills/yss-technical-design/tests/fixtures.mjs +32 -0
- package/template/.cursor/skills/yss-technical-design/tests/run-scenarios.mjs +82 -0
- package/template/.cursor/skills/yss-ui/SKILL.md +2 -0
- package/template/.pi/skills/yss-domain/SKILL.md +3 -3
- package/template/.pi/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +4 -2
- package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +5 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -2
- package/template/.pi/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +10 -1
- package/template/.pi/skills/yss-mvc-design/SKILL.md +16 -0
- package/template/.pi/skills/yss-mvc-design/agents/openai.yaml +4 -0
- package/template/.pi/skills/yss-mvc-design/references/mvc-design.schema.json +315 -0
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +4 -2
- package/template/.pi/skills/yss-product-lifecycle/references/artifact-dependencies.md +2 -2
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +14 -9
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +1 -1
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.pi/skills/yss-tactical-design/SKILL.md +2 -2
- package/template/.pi/skills/yss-tactical-design/references/output-template.md +2 -0
- package/template/.pi/skills/yss-tactical-design/references/tactical-design-contract.md +3 -1
- package/template/.pi/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +3 -2
- package/template/.pi/skills/yss-technical-design/SKILL.md +31 -0
- package/template/.pi/skills/yss-technical-design/agents/openai.yaml +4 -0
- package/template/.pi/skills/yss-technical-design/references/technical-design-common.schema.json +290 -0
- package/template/.pi/skills/yss-technical-design/references/technical-design-contract.md +31 -0
- package/template/.pi/skills/yss-technical-design/references/technical-design.schema.json +759 -0
- package/template/.pi/skills/yss-technical-design/scripts/generate-schema.mjs +20 -0
- package/template/.pi/skills/yss-technical-design/scripts/validate-technical-design.mjs +134 -0
- package/template/.pi/skills/yss-technical-design/tests/fixtures.mjs +32 -0
- package/template/.pi/skills/yss-technical-design/tests/run-scenarios.mjs +82 -0
- package/template/.pi/skills/yss-ui/SKILL.md +2 -0
- package/template/.qoder/skills/yss-domain/SKILL.md +3 -3
- package/template/.qoder/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
- package/template/.qoder/skills/yss-implementation-contract-compiler/SKILL.md +4 -2
- package/template/.qoder/skills/yss-implementation-contract-compiler/references/boundaries.md +5 -0
- package/template/.qoder/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -2
- package/template/.qoder/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +10 -1
- package/template/.qoder/skills/yss-mvc-design/SKILL.md +16 -0
- package/template/.qoder/skills/yss-mvc-design/agents/openai.yaml +4 -0
- package/template/.qoder/skills/yss-mvc-design/references/mvc-design.schema.json +315 -0
- package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +4 -2
- package/template/.qoder/skills/yss-product-lifecycle/references/artifact-dependencies.md +2 -2
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +14 -9
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration.md +1 -1
- package/template/.qoder/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.qoder/skills/yss-tactical-design/SKILL.md +2 -2
- package/template/.qoder/skills/yss-tactical-design/references/output-template.md +2 -0
- package/template/.qoder/skills/yss-tactical-design/references/tactical-design-contract.md +3 -1
- package/template/.qoder/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +3 -2
- package/template/.qoder/skills/yss-technical-design/SKILL.md +31 -0
- package/template/.qoder/skills/yss-technical-design/agents/openai.yaml +4 -0
- package/template/.qoder/skills/yss-technical-design/references/technical-design-common.schema.json +290 -0
- package/template/.qoder/skills/yss-technical-design/references/technical-design-contract.md +31 -0
- package/template/.qoder/skills/yss-technical-design/references/technical-design.schema.json +759 -0
- package/template/.qoder/skills/yss-technical-design/scripts/generate-schema.mjs +20 -0
- package/template/.qoder/skills/yss-technical-design/scripts/validate-technical-design.mjs +134 -0
- package/template/.qoder/skills/yss-technical-design/tests/fixtures.mjs +32 -0
- package/template/.qoder/skills/yss-technical-design/tests/run-scenarios.mjs +82 -0
- package/template/.qoder/skills/yss-ui/SKILL.md +2 -0
- package/template/.trae/skills/yss-domain/SKILL.md +3 -3
- package/template/.trae/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
- package/template/.trae/skills/yss-implementation-contract-compiler/SKILL.md +4 -2
- package/template/.trae/skills/yss-implementation-contract-compiler/references/boundaries.md +5 -0
- package/template/.trae/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +16 -2
- package/template/.trae/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +10 -1
- package/template/.trae/skills/yss-mvc-design/SKILL.md +16 -0
- package/template/.trae/skills/yss-mvc-design/agents/openai.yaml +4 -0
- package/template/.trae/skills/yss-mvc-design/references/mvc-design.schema.json +315 -0
- package/template/.trae/skills/yss-product-lifecycle/SKILL.md +4 -2
- package/template/.trae/skills/yss-product-lifecycle/references/artifact-dependencies.md +2 -2
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +14 -9
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration.md +1 -1
- package/template/.trae/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.trae/skills/yss-tactical-design/SKILL.md +2 -2
- package/template/.trae/skills/yss-tactical-design/references/output-template.md +2 -0
- package/template/.trae/skills/yss-tactical-design/references/tactical-design-contract.md +3 -1
- package/template/.trae/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +3 -2
- package/template/.trae/skills/yss-technical-design/SKILL.md +31 -0
- package/template/.trae/skills/yss-technical-design/agents/openai.yaml +4 -0
- package/template/.trae/skills/yss-technical-design/references/technical-design-common.schema.json +290 -0
- package/template/.trae/skills/yss-technical-design/references/technical-design-contract.md +31 -0
- package/template/.trae/skills/yss-technical-design/references/technical-design.schema.json +759 -0
- package/template/.trae/skills/yss-technical-design/scripts/generate-schema.mjs +20 -0
- package/template/.trae/skills/yss-technical-design/scripts/validate-technical-design.mjs +134 -0
- package/template/.trae/skills/yss-technical-design/tests/fixtures.mjs +32 -0
- package/template/.trae/skills/yss-technical-design/tests/run-scenarios.mjs +82 -0
- package/template/.trae/skills/yss-ui/SKILL.md +2 -0
- package/template/CONTEXT.md +4 -1
- package/template/README.md +4 -0
- package/template/docs/agents/digital-human-roles.yaml +3 -2
- package/template/docs/agents/yss-skill-registry.yaml +20 -1
- package/template/docs/architecture/templates/architecture-review-checklist.md +1 -1
- package/template/docs/architecture/templates/system-overview-design-template.md +15 -4
- package/template/docs/process/frontend-backend-delivery.md +72 -0
- package/template/docs/process/implementation-repo-integration.md +2 -0
- package/template/docs/process/lifecycle-artifact-map.md +3 -0
- package/template/docs/process/lifecycle-registry-baseline.json +4 -1
- package/template/docs/process/lifecycle-registry.yaml +14 -2
- package/template/docs/process/schemas/backend-delivery-verification.schema.json +113 -0
- package/template/docs/process/schemas/backend-delivery.schema.json +301 -0
- package/template/docs/process/schemas/digital-human-task-package.schema.json +8 -0
- package/template/docs/process/schemas/frontend-delivery-acceptance.schema.json +200 -0
- package/template/docs/process/schemas/frontend-implementation-evidence.schema.json +3 -0
- package/template/docs/process/schemas/strategic-design-handoff.schema.json +77 -4
- package/template/docs/process/strategic-handoff-package.md +4 -2
- package/template/docs/process/template-verification-profiles.yaml +20 -0
- package/template/docs/user-guide//346/210/230/346/234/257/350/256/276/350/256/241/345/255/220/351/241/271/347/233/256/347/224/250/346/210/267/346/211/213/345/206/214.md +21 -206
- package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +63 -963
- package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214/347/264/242/345/274/225.md +11 -14
- package/template/docs/user-guide//350/256/276/345/244/207/345/200/237/347/224/250/350/264/257/347/251/277/346/241/210/344/276/213.md +127 -0
- package/template/scripts/backend-delivery +14 -0
- package/template/scripts/fixtures/backend-delivery/revision-server.mjs +11 -0
- package/template/scripts/fixtures/strategic-handoff/fixture.mjs +3 -2
- package/template/scripts/instantiate-harness +69 -0
- package/template/scripts/lib/backend-delivery.mjs +164 -0
- package/template/scripts/lib/frontend-delivery-boundary.mjs +49 -0
- package/template/scripts/lib/frontend-delivery.mjs +73 -0
- package/template/scripts/lib/harness-execution-scope.mjs +52 -0
- package/template/scripts/lib/implementation-contract-compiler.mjs +19 -2
- package/template/scripts/lib/lifecycle-transition.mjs +7 -0
- package/template/scripts/lib/strategic-handoff-consumption.mjs +17 -10
- package/template/scripts/lib/strategic-handoff-design-targets.mjs +15 -0
- package/template/scripts/lib/strategic-handoff.mjs +1 -1
- package/template/scripts/lib/task-package.mjs +7 -0
- package/template/scripts/lib/technical-design-boundary.mjs +23 -0
- package/template/scripts/sync-strategic-handoff-tools +5 -2
- package/template/scripts/verify-frontend-delivery +9 -0
- package/template/scripts/verify-frontend-delivery-scenarios +131 -0
- package/template/scripts/verify-frontend-implementation-evidence +2 -0
- package/template/scripts/verify-strategic-handoff-package-scenarios +7 -1
- package/template/skills-lock.json +43 -13
- package/template.manifest.json +43 -1
- package/template.snapshot.json +5 -5
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
const load = ref => JSON.parse(readFileSync(new URL(ref, import.meta.url), 'utf8'));
|
|
5
|
+
const schema = load('../references/technical-design-common.schema.json');
|
|
6
|
+
const branches = [
|
|
7
|
+
['domain-driven', '../../yss-tactical-design/references/tactical-design.schema.json'],
|
|
8
|
+
['layered-mvc', '../../yss-mvc-design/references/mvc-design.schema.json']
|
|
9
|
+
];
|
|
10
|
+
schema.$comment = 'Generated by scripts/generate-schema.mjs from common and specialist schemas. Do not hand-edit.';
|
|
11
|
+
schema.allOf = branches.map(([family, ref]) => {
|
|
12
|
+
const branch = load(ref); delete branch.$id; delete branch.$schema;
|
|
13
|
+
return { if: { properties: { architecture: { properties: { family: { const: family } } } } }, then: { properties: { design: branch } } };
|
|
14
|
+
});
|
|
15
|
+
const output = fileURLToPath(new URL('../references/technical-design.schema.json', import.meta.url));
|
|
16
|
+
const bytes = `${JSON.stringify(schema, null, 2)}\n`;
|
|
17
|
+
if (process.argv.includes('--check')) {
|
|
18
|
+
if (readFileSync(output, 'utf8') !== bytes) throw new Error('技术设计 Schema 投影漂移,请运行 generate-schema.mjs');
|
|
19
|
+
} else writeFileSync(output, bytes);
|
|
20
|
+
process.stdout.write('技术设计分支 Schema 已同步\n');
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
5
|
+
import { parseArgs } from 'node:util';
|
|
6
|
+
import { assertScaffoldUserDecision } from '../../../../scripts/lib/user-decision.mjs';
|
|
7
|
+
import { validateJsonSchema } from '../../../../scripts/lib/json-schema.mjs';
|
|
8
|
+
import { read, safe, hash, digest, ensure } from '../../../../scripts/lib/strategic-handoff-io.mjs';
|
|
9
|
+
import { validate as validateDdd } from '../../yss-tactical-design/scripts/validate-tactical-design.mjs';
|
|
10
|
+
import { designTargets } from '../../../../scripts/lib/strategic-handoff-design-targets.mjs';
|
|
11
|
+
import { verifyConsumption } from '../../../../scripts/lib/strategic-handoff-consumption.mjs';
|
|
12
|
+
|
|
13
|
+
const schema = fileURLToPath(new URL('../references/technical-design.schema.json', import.meta.url));
|
|
14
|
+
const text = x => typeof x === 'string' && x.trim().length > 0;
|
|
15
|
+
const nonempty = xs => Array.isArray(xs) && xs.length > 0 && xs.every(text);
|
|
16
|
+
export const technicalDigest = data => digest(Object.fromEntries(Object.entries(data).filter(([key]) => key !== 'digest')));
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
function validateMvc(design) {
|
|
20
|
+
const modules = new Map(design.module_catalog.map(item => [item.module_id, item]));
|
|
21
|
+
const cases = new Map(design.use_case_catalog.map(item => [item.use_case_id, item]));
|
|
22
|
+
const rules = new Set(design.rule_catalog.map(item => item.rule_id));
|
|
23
|
+
const permitted = {
|
|
24
|
+
server: ['service','core','client'], service: ['repository','adapter'], core: ['repository','adapter'],
|
|
25
|
+
repository: [], adapter: ['client','feign-client'], client: [], 'feign-client': ['client']
|
|
26
|
+
};
|
|
27
|
+
for (const module of modules.values()) for (const ref of module.depends_on) {
|
|
28
|
+
ensure(modules.has(ref) && permitted[module.layer].includes(modules.get(ref).layer), `模块依赖越界: ${module.module_id} -> ${ref}`);
|
|
29
|
+
}
|
|
30
|
+
for (const item of cases.values()) {
|
|
31
|
+
ensure(['service','core'].includes(modules.get(item.module_ref)?.layer), `用例必须属于 service/core: ${item.use_case_id}`);
|
|
32
|
+
ensure(item.rule_refs.every(ref => rules.has(ref)), `用例引用未声明规则: ${item.use_case_id}`);
|
|
33
|
+
}
|
|
34
|
+
for (const rule of design.rule_catalog) ensure(rule.use_case_refs.every(ref => cases.has(ref) && cases.get(ref).rule_refs.includes(rule.rule_id)), `规则与用例未双向关联: ${rule.rule_id}`);
|
|
35
|
+
for (const item of design.state_transition_catalog) ensure(cases.has(item.use_case_ref), '状态转换引用未声明用例');
|
|
36
|
+
if (!design.state_transition_catalog.length) ensure(text(design.state_not_applicable_reason), '无状态转换必须说明原因');
|
|
37
|
+
for (const item of design.persistence_mapping) ensure(cases.has(item.use_case_ref) && modules.get(item.repository_ref)?.layer === 'repository', '持久化映射的用例或 Repository 引用无效');
|
|
38
|
+
for (const item of design.integration_catalog) ensure(modules.get(item.adapter_ref)?.layer === 'adapter', '外部集成必须关联 Adapter');
|
|
39
|
+
if (!design.integration_catalog.length) ensure(text(design.integration_not_applicable_reason), '无外部集成必须说明原因');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function verifyArchitecture(data, root) {
|
|
43
|
+
const binding = data.architecture;
|
|
44
|
+
const file = safe(root, binding.decision_ref);
|
|
45
|
+
ensure(hash(readFileSync(file)) === binding.decision_digest, '架构来源摘要漂移');
|
|
46
|
+
const record = read(file);
|
|
47
|
+
if (binding.source_kind === 'scaffold-decision') {
|
|
48
|
+
const decision = record.decisions?.find(item => item.project_id === binding.project_id);
|
|
49
|
+
ensure(record.status === 'current' && record.template === false, '架构选择记录必须为当前正式记录');
|
|
50
|
+
ensure(decision && ['user-confirmed','lifecycle-approved','consumed'].includes(decision.status), '分支设计前必须确认项目架构');
|
|
51
|
+
ensure(decision.confirmed_architecture === binding.family, '技术设计与确认架构不匹配');
|
|
52
|
+
ensure(text(decision.user_confirmation?.confirmation_ref) && text(decision.user_confirmation?.confirmed_by), '缺少真实架构确认引用');
|
|
53
|
+
assertScaffoldUserDecision(decision, { root });
|
|
54
|
+
} else {
|
|
55
|
+
// Registration formats differ by repository; bind the actual registered identity,
|
|
56
|
+
// never infer architecture from a directory or a design's self-declaration.
|
|
57
|
+
const entry = record.repositories?.find(item => item.project_id === binding.project_id) ?? record;
|
|
58
|
+
ensure(entry.project_id === binding.project_id && entry.architecture_identity?.architecture_family === binding.family, '技术设计与既有工程登记架构不匹配');
|
|
59
|
+
ensure(!['stale','blocked'].includes(record.status) && !['stale','blocked'].includes(entry.status), '工程登记已失效');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function validateLocalTraceability(data, root, sliceRef) {
|
|
64
|
+
const { ids, seams } = designTargets(data);
|
|
65
|
+
const sources = new Map(data.source_items.map(item => [item.source_id, item]));
|
|
66
|
+
ensure(sources.size === data.source_items.length, '源规则或场景 ID 重复');
|
|
67
|
+
const rows = new Map(data.traceability.map(item => [item.source_id, item]));
|
|
68
|
+
ensure(rows.size === data.traceability.length, '承接记录重复');
|
|
69
|
+
ensure(data.strategic_handoff || sources.size > 0, '无战略包时必须列出需求规则与场景');
|
|
70
|
+
for (const source of sources.values()) ensure(data.inputs.some(item => item.ref === source.source_ref), '源规则或场景未绑定当前输入');
|
|
71
|
+
for (const id of rows.keys()) ensure(sources.has(id), `未知承接来源: ${id}`);
|
|
72
|
+
for (const [id, source] of sources) {
|
|
73
|
+
const row = rows.get(id);
|
|
74
|
+
ensure(row, `缺少规则或场景承接: ${id}`);
|
|
75
|
+
if (row.disposition === 'implemented') {
|
|
76
|
+
ensure(nonempty(row.tactical_refs) && row.tactical_refs.every(ref => ids.has(ref)), `设计落点悬空: ${id}`);
|
|
77
|
+
ensure(nonempty(row.test_seam_refs) && row.test_seam_refs.every(ref => seams.has(ref) && row.tactical_refs.includes(seams.get(ref).subject_ref)), `测试 seam 未关联设计落点: ${id}`);
|
|
78
|
+
if (source.kind === 'scenario' && source.critical) ensure(['success','failure'].every(outcome => row.scenario_tests?.some(test => test.outcome === outcome && row.test_seam_refs.includes(test.seam_ref))), `关键场景缺少成功/失败测试: ${id}`);
|
|
79
|
+
ensure(nonempty(row.evidence_refs), `缺少承接证据: ${id}`);
|
|
80
|
+
} else if (row.disposition === 'not-applicable') {
|
|
81
|
+
ensure(text(row.reason) && nonempty(row.evidence_refs), `不适用缺少依据: ${id}`);
|
|
82
|
+
} else {
|
|
83
|
+
if (row.disposition === 'deferred') for (const key of ['reason','risk','owner','followup_ticket_ref','verification_plan','target_version']) ensure(text(row[key]), `延期缺少 ${key}: ${id}`);
|
|
84
|
+
ensure(sliceRef && row.dependency_status === 'known' && nonempty(row.dependent_slice_refs) && !row.dependent_slice_refs.includes(sliceRef), `未闭合承接阻断当前范围: ${id}`);
|
|
85
|
+
}
|
|
86
|
+
for (const ref of row.evidence_refs || []) safe(root, ref);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function validateTechnicalDesign(data, { root = process.cwd(), sliceRef, legacyDdd = false } = {}) {
|
|
91
|
+
if (data?.schema_version === 1) {
|
|
92
|
+
ensure(legacyDdd, '旧 v1 合同需要显式 --legacy-ddd,仅按 DDD 兼容读取');
|
|
93
|
+
const errors = validateDdd(data);
|
|
94
|
+
ensure(!errors.length, errors.join('; '));
|
|
95
|
+
if (sliceRef) ensure(data.status === 'approved', '切片只能消费 approved 设计');
|
|
96
|
+
if (data.strategic_handoff || data.strategic_context_import_ref || data.upstream_impact?.source_kind === 'strategic-handoff') {
|
|
97
|
+
const result = await verifyConsumption(data, { root, sliceRef });
|
|
98
|
+
ensure(result.result === 'verified', JSON.stringify(result));
|
|
99
|
+
}
|
|
100
|
+
return { result: 'legacy-ddd-read-only', architecture_family: 'domain-driven', status: data.status };
|
|
101
|
+
}
|
|
102
|
+
validateJsonSchema(data, schema, { label: '技术设计合同' });
|
|
103
|
+
ensure(data.digest === technicalDigest(data), '技术设计合同摘要不匹配');
|
|
104
|
+
ensure(!['stale','blocked','drift','new_impacts'].includes(data.status), '设计状态不可消费');
|
|
105
|
+
if (sliceRef) ensure(data.status === 'approved', '切片只能消费 approved 设计');
|
|
106
|
+
verifyArchitecture(data, root);
|
|
107
|
+
ensure(data.inputs.some(item => item.kind === 'context' && item.ref === 'CONTEXT.md') && data.inputs.some(item => item.kind === 'spec'), '共同输入缺少根 CONTEXT.md 或 Spec');
|
|
108
|
+
for (const input of data.inputs) ensure(hash(readFileSync(safe(root, input.ref))) === input.digest, `输入摘要漂移: ${input.ref}`);
|
|
109
|
+
for (const ref of data.evidence_refs) safe(root, ref);
|
|
110
|
+
if (data.status === 'approved') ensure(data.evidence_refs.length > 0, '已批准设计缺少评审证据');
|
|
111
|
+
if (data.architecture.family === 'domain-driven') {
|
|
112
|
+
const errors = validateDdd(data.design);
|
|
113
|
+
ensure(!errors.length, errors.join('; '));
|
|
114
|
+
ensure(data.design.status === data.status, 'DDD 分支状态与共同合同不一致');
|
|
115
|
+
ensure(data.inputs.some(item => item.kind === 'strategic'), 'DDD 分支缺少战略领域输入');
|
|
116
|
+
ensure(!data.design.strategic_handoff && !data.design.strategic_context_import_ref, '战略绑定只允许在共同合同中维护');
|
|
117
|
+
} else validateMvc(data.design);
|
|
118
|
+
const { ids, seams } = designTargets(data);
|
|
119
|
+
for (const seam of seams.values()) ensure(ids.has(seam.subject_ref), `测试 seam 设计对象悬空: ${seam.seam_id}`);
|
|
120
|
+
validateLocalTraceability(data, root, sliceRef);
|
|
121
|
+
if (data.strategic_handoff) {
|
|
122
|
+
const result = await verifyConsumption(data, { root, sliceRef });
|
|
123
|
+
ensure(result.result === 'verified', JSON.stringify(result));
|
|
124
|
+
}
|
|
125
|
+
return { result: 'ready-for-lifecycle-review', technical_design_id: data.technical_design_id, architecture_family: data.architecture.family, status: data.status, digest: data.digest };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function main() {
|
|
129
|
+
const { values, positionals } = parseArgs({ allowPositionals: true, options: { root: { type: 'string', default: process.cwd() }, slice: { type: 'string' }, 'legacy-ddd': { type: 'boolean', default: false } } });
|
|
130
|
+
ensure(positionals.length === 1, '用法: validate-technical-design.mjs <合同> --root <项目根> [--slice <ID>] [--legacy-ddd]');
|
|
131
|
+
const result = await validateTechnicalDesign(read(path.resolve(positionals[0])), { root: values.root, sliceRef: values.slice, legacyDdd: values['legacy-ddd'] });
|
|
132
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
133
|
+
}
|
|
134
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) main().catch(error => { process.stderr.write(`${JSON.stringify({ result: 'blocked', errors: [error.message] })}\n`); process.exitCode = 1; });
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { writeFileSync, readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { hash } from '../../../../scripts/lib/strategic-handoff-io.mjs';
|
|
4
|
+
import { technicalDigest } from '../scripts/validate-technical-design.mjs';
|
|
5
|
+
export function mvcFixture(root) {
|
|
6
|
+
const files = {
|
|
7
|
+
'CONTEXT.md': '# 业务上下文\n',
|
|
8
|
+
'spec.md': '# 需求\nrule.valid: 必填材料完整。scenario.submit: 提交成功或校验失败。\n',
|
|
9
|
+
'registration.json': JSON.stringify({ project_id: 'example', status: 'current', architecture_identity: { architecture_family: 'layered-mvc' } }),
|
|
10
|
+
'review.md': '设计评审测试证据;不构成真实批准。\n'
|
|
11
|
+
};
|
|
12
|
+
for (const [ref, bytes] of Object.entries(files)) writeFileSync(path.join(root, ref), bytes);
|
|
13
|
+
const data = {
|
|
14
|
+
schema_version: 2, technical_design_id: 'technical-design.example', version: 'v1', status: 'ready-for-human', context_ref: 'CONTEXT.md',
|
|
15
|
+
architecture: { family: 'layered-mvc', project_id: 'example', source_kind: 'existing-registration', decision_ref: 'registration.json', decision_digest: hash(readFileSync(path.join(root, 'registration.json'))) },
|
|
16
|
+
inputs: ['CONTEXT.md','spec.md'].map((ref,index) => ({ kind: index ? 'spec' : 'context', ref, version: 'v1', digest: hash(readFileSync(path.join(root,ref))) })),
|
|
17
|
+
source_items: [{ source_id: 'rule.valid', kind: 'rule', critical: false, source_ref: 'spec.md' }, { source_id: 'scenario.submit', kind: 'scenario', critical: true, source_ref: 'spec.md' }],
|
|
18
|
+
traceability: ['rule.valid','scenario.submit'].map(source_id => ({ source_id, disposition: 'implemented', tactical_refs: ['use-case.submit'], test_seam_refs: ['test-seam.success','test-seam.failure'], evidence_refs: ['spec.md'], dependency_status: 'known', dependent_slice_refs: ['slice.submit'], scenario_tests: [{ outcome: 'success', seam_ref: 'test-seam.success' }, { outcome: 'failure', seam_ref: 'test-seam.failure' }] })),
|
|
19
|
+
design: {
|
|
20
|
+
module_catalog: [{ module_id: 'module.server', layer: 'server', responsibility: 'HTTP 适配', depends_on: ['module.service'] }, { module_id: 'module.service', layer: 'service', responsibility: '提交用例和事务', depends_on: ['module.repository'] }, { module_id: 'module.repository', layer: 'repository', responsibility: '数据持久化', depends_on: [] }],
|
|
21
|
+
use_case_catalog: [{ use_case_id: 'use-case.submit', module_ref: 'module.service', flow: ['校验材料','保存申请'], rule_refs: ['rule.valid'], failure_handling: '材料不完整拒绝提交,写入失败回滚' }],
|
|
22
|
+
rule_catalog: [{ rule_id: 'rule.valid', statement: '材料必须完整', use_case_refs: ['use-case.submit'] }],
|
|
23
|
+
state_transition_catalog: [], state_not_applicable_reason: '本范围只登记申请,无状态流转',
|
|
24
|
+
consistency_policy: { transaction_boundary: '一次提交同一事务', rollback: '写入失败整体回滚', concurrency: '唯一约束拒绝竞争提交', idempotency: '请求键唯一' },
|
|
25
|
+
persistence_mapping: [{ mapping_id: 'mapping.application', use_case_ref: 'use-case.submit', repository_ref: 'module.repository', storage_model: 'application', notes: '请求键唯一' }],
|
|
26
|
+
integration_catalog: [], integration_not_applicable_reason: '无外部集成',
|
|
27
|
+
test_seams: [{ seam_id: 'test-seam.success', kind: 'service', subject_ref: 'use-case.submit', assertion: '完整材料保存成功' }, { seam_id: 'test-seam.failure', kind: 'service', subject_ref: 'use-case.submit', assertion: '缺材料时不写入' }]
|
|
28
|
+
}, evidence_refs: ['review.md']
|
|
29
|
+
};
|
|
30
|
+
data.digest = technicalDigest(data);
|
|
31
|
+
return data;
|
|
32
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtempSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { attachScaffoldDecisionFixture } from '../../../../scripts/fixtures/user-decision/build-fixture.mjs';
|
|
8
|
+
import { mvcFixture } from './fixtures.mjs';
|
|
9
|
+
import { technicalDigest, validateTechnicalDesign } from '../scripts/validate-technical-design.mjs';
|
|
10
|
+
import { hash, read } from '../../../../scripts/lib/strategic-handoff-io.mjs';
|
|
11
|
+
import { enforceTechnicalDesign } from '../../../../scripts/lib/technical-design-boundary.mjs';
|
|
12
|
+
import { compileDefaultImplementationContract, evaluateContractFreshness, loadCompilerContract } from '../../../../scripts/lib/implementation-contract-compiler.mjs';
|
|
13
|
+
import { loadSkillRegistry } from '../../../../scripts/lib/skill-registry.mjs';
|
|
14
|
+
const root = mkdtempSync(path.join(tmpdir(), 'yss-technical-design-'));
|
|
15
|
+
let checks = 0;
|
|
16
|
+
try {
|
|
17
|
+
const mvc = mvcFixture(root);
|
|
18
|
+
const validate = data => validateTechnicalDesign(data, { root });
|
|
19
|
+
assert.equal((await validate(mvc)).architecture_family, 'layered-mvc'); checks++;
|
|
20
|
+
async function rejected(change, pattern) {
|
|
21
|
+
const data = structuredClone(mvc); change(data); data.digest = technicalDigest(data);
|
|
22
|
+
await assert.rejects(() => validate(data), pattern); checks++;
|
|
23
|
+
}
|
|
24
|
+
await rejected(d => { d.architecture.family = 'mixed'; }, /not one of/);
|
|
25
|
+
await rejected(d => { d.architecture.project_id = 'wrong'; }, /登记架构不匹配/);
|
|
26
|
+
await rejected(d => { d.architecture.decision_digest = `sha256:${'0'.repeat(64)}`; }, /来源摘要漂移/);
|
|
27
|
+
await rejected(d => { d.traceability.pop(); }, /缺少规则或场景承接/);
|
|
28
|
+
await rejected(d => { d.traceability[1].scenario_tests.pop(); }, /成功\/失败测试/);
|
|
29
|
+
await rejected(d => { d.traceability[0].tactical_refs = ['aggregate.fake']; }, /设计落点悬空/);
|
|
30
|
+
await rejected(d => { d.design.module_catalog[0].depends_on = ['module.repository']; }, /模块依赖越界/);
|
|
31
|
+
await rejected(d => { d.design.consistency_policy.transaction_boundary = ''; }, /non-empty/);
|
|
32
|
+
await rejected(d => { d.design.aggregate_catalog = []; }, /Additional properties/);
|
|
33
|
+
await rejected(d => { d.design.test_seams[0].subject_ref = 'missing'; }, /设计对象悬空/);
|
|
34
|
+
await rejected(d => { d.status = 'stale'; }, /状态不可消费/);
|
|
35
|
+
await rejected(d => { d.traceability[0].disposition = 'conflict'; }, /未闭合承接/);
|
|
36
|
+
const deferred = structuredClone(mvc); deferred.status = 'approved';
|
|
37
|
+
Object.assign(deferred.traceability[0], { disposition: 'deferred', reason: '下一版', risk: '提交不可用', owner: '维护者', followup_ticket_ref: 'ticket.next', verification_plan: '回归提交', target_version: 'v2' });
|
|
38
|
+
deferred.digest = technicalDigest(deferred);
|
|
39
|
+
await assert.rejects(() => validateTechnicalDesign(deferred, { root, sliceRef: 'slice.submit' }), /未闭合承接/); checks++;
|
|
40
|
+
assert.equal((await validateTechnicalDesign(deferred, { root, sliceRef: 'slice.other' })).architecture_family, 'layered-mvc'); checks++;
|
|
41
|
+
deferred.traceability[0].dependency_status = 'unknown'; deferred.digest = technicalDigest(deferred);
|
|
42
|
+
await assert.rejects(() => validateTechnicalDesign(deferred, { root, sliceRef: 'slice.other' }), /未闭合承接/); checks++;
|
|
43
|
+
writeFileSync(path.join(root, 'spec.md'), 'changed');
|
|
44
|
+
await assert.rejects(() => validate(mvc), /输入摘要漂移/); checks++;
|
|
45
|
+
mvcFixture(root);
|
|
46
|
+
const old = read(fileURLToPath(new URL('../../yss-tactical-design/tests/fixtures/valid-tactical-design.yaml', import.meta.url)));
|
|
47
|
+
await assert.rejects(() => validate(old), /显式 --legacy-ddd/); checks++;
|
|
48
|
+
assert.equal((await validateTechnicalDesign(old, { root, legacyDdd: true })).result, 'legacy-ddd-read-only'); checks++;
|
|
49
|
+
const ddd = structuredClone(mvc); ddd.architecture.family = 'domain-driven';
|
|
50
|
+
writeFileSync(path.join(root, 'registration.json'), JSON.stringify({ project_id: 'example', status: 'current', architecture_identity: { architecture_family: 'domain-driven' } }));
|
|
51
|
+
ddd.architecture.decision_digest = hash(readFileSync(path.join(root, 'registration.json'))); ddd.design = old;
|
|
52
|
+
ddd.inputs.push({ kind: 'strategic', ref: 'spec.md', version: 'v1', digest: hash(readFileSync(path.join(root, 'spec.md'))) });
|
|
53
|
+
for (const row of ddd.traceability) Object.assign(row, { tactical_refs: [old.test_seams[0].subject_ref], test_seam_refs: [old.test_seams[0].seam_id], scenario_tests: ['success','failure'].map(outcome => ({ outcome, seam_ref: old.test_seams[0].seam_id })) });
|
|
54
|
+
ddd.digest = technicalDigest(ddd);
|
|
55
|
+
assert.equal((await validate(ddd)).architecture_family, 'domain-driven'); checks++;
|
|
56
|
+
ddd.design.aggregate_catalog[0].api_exposure = 'public'; ddd.digest = technicalDigest(ddd);
|
|
57
|
+
await assert.rejects(() => validate(ddd), /internal-only/); checks++;
|
|
58
|
+
const scaffold = mvcFixture(root);
|
|
59
|
+
const decision = attachScaffoldDecisionFixture(path.join(root, 'decision-evidence'), { project_id: 'example', status: 'user-confirmed', confirmed_architecture: 'layered-mvc', decision_inputs_digest: `sha256:${'1'.repeat(64)}`, user_confirmation: { confirmation_ref: 'user-message', confirmed_by: 'user' } });
|
|
60
|
+
const record = { status: 'current', template: false, decisions: [decision] };
|
|
61
|
+
const recordFile = path.join(root, 'decision.json');
|
|
62
|
+
writeFileSync(recordFile, JSON.stringify(record));
|
|
63
|
+
scaffold.architecture = { ...scaffold.architecture, source_kind: 'scaffold-decision', decision_ref: 'decision.json', decision_digest: hash(readFileSync(recordFile)) }; scaffold.digest = technicalDigest(scaffold);
|
|
64
|
+
assert.equal((await validate(scaffold)).architecture_family, 'layered-mvc'); checks++;
|
|
65
|
+
record.decisions[0].status = 'awaiting-user-decision'; writeFileSync(recordFile, JSON.stringify(record)); scaffold.architecture.decision_digest = hash(readFileSync(recordFile)); scaffold.digest = technicalDigest(scaffold);
|
|
66
|
+
await assert.rejects(() => validate(scaffold), /分支设计前必须确认/); checks++;
|
|
67
|
+
record.decisions[0].status = 'user-confirmed'; record.decisions[0].user_confirmation.user_decision_ref = 'missing-user-decision.json'; writeFileSync(recordFile, JSON.stringify(record)); scaffold.architecture.decision_digest = hash(readFileSync(recordFile)); scaffold.digest = technicalDigest(scaffold);
|
|
68
|
+
await assert.rejects(() => validate(scaffold), /user-decision/); checks++;
|
|
69
|
+
const current = mvcFixture(root); current.status = 'approved'; current.digest = technicalDigest(current);
|
|
70
|
+
const file = path.join(root, 'design.json'); writeFileSync(file, JSON.stringify(current));
|
|
71
|
+
const technical_design = { ref: 'design.json', version: 'v1', digest: hash(readFileSync(file)) };
|
|
72
|
+
const identity = { architecture_family: 'layered-mvc', architecture_profile: 'layered-mvc-service', generator_skill: 'yss-layered-mvc-scaffold-generator', requested_capabilities: [], resolved_modules: ['server','service','repository'], verification_database: 'h2', production_database: 'not-bound', contract_digest: 'a'.repeat(64) };
|
|
73
|
+
const state = { technical_design, slice_id: 'slice.submit', architecture_identity: identity, conditions: ['backend-technical-design-impact'] };
|
|
74
|
+
enforceTechnicalDesign(state, { root }); checks++;
|
|
75
|
+
assert.throws(() => enforceTechnicalDesign({ ...state, technical_design: undefined }, { root }), /缺少已批准技术设计/); checks++;
|
|
76
|
+
assert.throws(() => enforceTechnicalDesign({ ...state, architecture_identity: { architecture_family: 'domain-driven' } }, { root }), /架构不匹配/); checks++;
|
|
77
|
+
const resolution = compileDefaultImplementationContract({ ...state, root, requiredCapabilities: ['contract.request-validation'], architecture_evidence: { engineering_baseline: identity, repository_registration: identity, manifest: identity } });
|
|
78
|
+
assert.deepEqual(resolution.technical_design, technical_design); assert(!resolution.required_skills.includes('yss-domain')); checks++;
|
|
79
|
+
writeFileSync(path.join(root, 'spec.md'), 'changed again');
|
|
80
|
+
assert.equal(evaluateContractFreshness({ schema_version: 2, resolution }, { registry: loadSkillRegistry(), compilerContract: loadCompilerContract(), root }).freshness, 'stale'); checks++;
|
|
81
|
+
} finally { rmSync(root, { recursive: true, force: true }); }
|
|
82
|
+
process.stdout.write(`技术设计场景通过:${checks} 项(MVC、DDD、兼容、架构、承接、切片与漂移)\n`);
|
|
@@ -22,6 +22,8 @@ description: Use when implementing or reviewing YSS Vue pages that combine YSS w
|
|
|
22
22
|
|
|
23
23
|
## 2. 执行前版本预检
|
|
24
24
|
|
|
25
|
+
采用专职前端 profile 或显式 `frontend_delivery` 绑定时,先按 `docs/process/frontend-backend-delivery.md` 实际核验战略与后端联合交付。缺任一输入只能诊断和回交;输入通过后准备计划/合同,正式实现、生成和恢复仍须当前批准的 Slice Contract 冻结接收摘要。接口或部署版本漂移时重新接收,不复用旧成功输出。
|
|
26
|
+
|
|
25
27
|
进入实现前从前端工程根目录执行:
|
|
26
28
|
|
|
27
29
|
```bash
|
|
@@ -5,7 +5,7 @@ description: 用于构建或重构 YSS 领域层代码。当用户要求设计
|
|
|
5
5
|
|
|
6
6
|
# yss-domain
|
|
7
7
|
|
|
8
|
-
这是一个领域实现 skill
|
|
8
|
+
这是一个领域实现 skill。核心目标是消费已批准的战术模型,将领域行为落实为代码;`yss-technical-design` 组织 DDD 分支,由 `yss-tactical-design` 设计、`yss-product-lifecycle` 维护批准。
|
|
9
9
|
|
|
10
10
|
本 skill 在新脚手架链路只支持 `domain-driven` / `target-domain-model`。`layered-mvc-service` 与 `mvc-data-analysis-v1` 是独立 MVC Profile,不是失败的 DDD 工程;它们不加载本 skill,也不生成 Domain Gateway。既有旧架构不在本链路内迁移。
|
|
11
11
|
|
|
@@ -23,7 +23,7 @@ description: 用于构建或重构 YSS 领域层代码。当用户要求设计
|
|
|
23
23
|
|
|
24
24
|
## 工作方式
|
|
25
25
|
|
|
26
|
-
1. 先读取批准且版本当前的 tactical-design contract
|
|
26
|
+
1. 先读取批准且版本当前的 Technical Design Contract 的 DDD `design` 分支和 Slice Implementation Contract;旧 v1 tactical-design contract 只按 DDD 显式兼容读取。
|
|
27
27
|
2. 数据库字段只做补充,不直接决定领域对象结构。
|
|
28
28
|
3. 按合同实现领域行为、状态机、不变量和 Gateway 边界。
|
|
29
29
|
4. 规则不清晰或模型需要扩展时,返回 `new_impacts` / `drift` 并停止,不要静默猜测。
|
|
@@ -64,7 +64,7 @@ description: 用于构建或重构 YSS 领域层代码。当用户要求设计
|
|
|
64
64
|
## 阶段 7 合同
|
|
65
65
|
|
|
66
66
|
- 只消费生命周期已批准的 `Slice Implementation Contract` 和当前 `work_unit`;不得扩大 `allowed_write_paths`。
|
|
67
|
-
- `Slice Implementation Contract` 必须引用批准且版本当前的 `tactical_design_ref
|
|
67
|
+
- `Slice Implementation Contract` 必须引用批准且版本当前的 `technical_design` 绑定(旧 DDD 显式兼容 `tactical_design_ref`);不得在实现阶段重新批准或替换聚合、不变量和一致性策略。
|
|
68
68
|
- 领域规则、状态机和不变量必须使用 `behavior-tdd`,先形成失败测试,再实现最小行为。
|
|
69
69
|
- 完成后按 `yss-implementation-contract-compiler/references/yss-skill-execution-result.md` 返回统一 `YSS Skill Execution Result`:changed files、领域/测试证据、实际验证结果、偏离和新增影响。
|
|
70
70
|
- 发现新 API、权限、状态机、数据模型或架构影响时填入 `new_impacts` 并暂停,不得静默扩张切片。
|
|
@@ -30,6 +30,8 @@ branch: template
|
|
|
30
30
|
|
|
31
31
|
## Workflow
|
|
32
32
|
|
|
33
|
+
采用专职前端 profile 或显式 `frontend_delivery` 绑定时,先按 `docs/process/frontend-backend-delivery.md` 实际核验战略与后端联合交付。缺任一输入只能诊断和回交;输入通过后准备计划/合同,正式实现、生成和恢复仍须当前批准的 Slice Contract 冻结接收摘要。接口或部署版本漂移时重新接收,不复用旧成功输出。
|
|
34
|
+
|
|
33
35
|
1. 确认当前任务已经通过 Harness 入口分诊,且实现位置已记录在 proposal、design、build entry review、实施计划或实现路由记录中。
|
|
34
36
|
2. 确认目标是外部实现仓库;只有用户明确选择时才输出到 Harness 仓库的 `apps/frontend/<project>/`。`apps/frontend/` 只能作为项目容器,`app/frontend/`、`app/backend/` 及其子路径禁止作为输出位置。`git-submodule` 只能在已初始化且附加分支的子仓工作树生成;空 gitlink、detached HEAD、`--force` 覆盖挂载点不得当成普通目录。
|
|
35
37
|
3. 只读检查模板分支是否可访问:`git ls-remote --heads <repo> template`。
|
|
@@ -26,12 +26,14 @@ description: Use when a YSS vertical slice is entering implementation, spans mul
|
|
|
26
26
|
|
|
27
27
|
## 硬规则
|
|
28
28
|
|
|
29
|
+
采用专职前端 profile 或显式 `frontend_delivery` 绑定时,先按 `docs/process/frontend-backend-delivery.md` 实际核验战略与后端联合交付。缺任一输入只能诊断和回交;输入通过后准备计划/合同,正式实现、生成和恢复仍须当前批准的 Slice Contract 冻结接收摘要。接口或部署版本漂移时重新接收,不复用旧成功输出。
|
|
30
|
+
|
|
29
31
|
- 编译器不得输出 `approved`、`ready-for-agent` 或 `completed`。
|
|
30
32
|
- Registry、Slice Contract 或编译器合同 schema v1 一律拒绝并给出迁移到 v2 的提示;不自动升级,不提供旧技能名兼容。
|
|
31
33
|
- `required_capabilities` 与 `required_skills` 必须同时冻结;Registry 或编译器摘要变化后合同立即 `stale`,重新编译后仍须交生命周期重新批准。
|
|
32
34
|
- UI 影响缺少正式原型确认、批准且 digest 当前的 Visual Baseline manifest 或当前切片 `case_id` 时,不得路由页面实现。模型必须先读 manifest 与语义引用,再查看对应 PNG;禁止目录 glob 和图片独立猜义。
|
|
33
35
|
- Repository/数据模型影响缺少数据架构时,不得路由持久化实现。
|
|
34
|
-
-
|
|
36
|
+
- 后端技术设计由 `yss-technical-design` 先行组织。消费批准且版本当前的 Technical Design Contract,核对其架构与工程基线一致;DDD 才消费聚合、Gateway 等战术字段并路由 `yss-domain`,MVC 消费用例、分层、规则和事务设计并按 Profile 路由。旧 v1 战术合同只按 DDD 显式兼容读取。无相关影响记录带原因的 `not-applicable`。
|
|
35
37
|
- API 变化必须回到生命周期 Draft/Review/Freeze;半成品 backend 不得冒充稳定 source of truth。
|
|
36
38
|
- 后端端到端切片必须包含 Application;对象/POJO 影响按契约自动补 `mapstruct`、`lombok`、`alibaba-java-code-style`。
|
|
37
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` 必须为显式布尔值。
|
|
@@ -58,4 +60,4 @@ description: Use when a YSS vertical slice is entering implementation, spans mul
|
|
|
58
60
|
|
|
59
61
|
跨仓交接使用 `scripts/strategic-handoff export / verify / import`。正式导出前补齐源战略的稳定规则 ID、关键场景和当前批准绑定;源资产原字节冻结、包内路径通过清单解析。目标导入只产生快照和对账/承接草案,正式 reconciliation 通过后才能进入战术设计。流程与字段见 `docs/process/strategic-handoff-package.md`。
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
来自战略交接包的技术设计合同(DDD / MVC)必须绑定 `strategic_handoff` 导入收据、包摘要、正式目标对账及逐条承接 rows。来自导入包时禁止仅填 `upstream_current: true`。批准前执行 `scripts/verify-strategic-handoff-consumption --root <target> <tactical>`;存在受控延期时按切片执行 `--slice <slice-id>`,实际核验通过且合同批准后才可继续相关切片。最新源规则、关键场景或资产变化使依赖项 stale;未知依赖扩大阻断,业务冲突回交战略方。结果绑定当前包与战术摘要,不能复用旧输出宣布 ready-for-agent。
|
package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
| Capability | Primary skill | Task modes |
|
|
20
20
|
| --- | --- | --- |
|
|
21
|
+
| `architecture.technical-design` | `yss-technical-design` | `guidance`, `integration`, `review-input` |
|
|
22
|
+
| `architecture.mvc-design` | `yss-mvc-design` | `guidance`, `integration`, `review-input` |
|
|
21
23
|
| `layer.mvc-service` | `yss-application` | `guidance`, `integration`, `slice-implementation`, `troubleshooting`, `review-input` |
|
|
22
24
|
| `layer.mvc-persistence` | `yss-repository` | `guidance`, `integration`, `slice-implementation`, `troubleshooting`, `review-input` |
|
|
23
25
|
| `layer.mvc-web` | `yss-web-controller` | `guidance`, `integration`, `slice-implementation`, `troubleshooting`, `review-input` |
|
|
@@ -112,6 +114,9 @@
|
|
|
112
114
|
| `yss-domain` | `domain-modeling` | `coordination-only` | — |
|
|
113
115
|
| `yss-domain` | `yss-tactical-design` | `context-conditional` | `tactical-domain` |
|
|
114
116
|
| `yss-domain` | `lombok` | `context-conditional` | `pojo` |
|
|
117
|
+
| `yss-technical-design` | `yss-tactical-design` | `coordination-only` | `domain-driven` |
|
|
118
|
+
| `yss-technical-design` | `yss-mvc-design` | `coordination-only` | `layered-mvc` |
|
|
119
|
+
| `yss-mvc-design` | `yss-openapi-draft-review` | `review-only` | `api-impact` |
|
|
115
120
|
| `yss-tactical-design` | `domain-modeling` | `coordination-only` | — |
|
|
116
121
|
| `yss-tactical-design` | `yss-openapi-draft-review` | `review-only` | `api-impact` |
|
|
117
122
|
| `yss-tactical-design` | `yss-repository` | `component-dependency` | `data-impact` |
|
|
@@ -61,6 +61,12 @@ readiness:
|
|
|
61
61
|
data_impact: [data_architecture]
|
|
62
62
|
backend_impact: [engineering_baseline, backend_repository, maven_wrapper]
|
|
63
63
|
cross_repo: [repository_registry, delivery_order, integration_verification, rollback_order]
|
|
64
|
+
frontend_delivery:
|
|
65
|
+
when: specialized-frontend-profile-or-explicit-frontend-delivery-binding
|
|
66
|
+
source: docs/process/frontend-backend-delivery.md
|
|
67
|
+
verifier: scripts/verify-frontend-delivery
|
|
68
|
+
output_binding: frontend.delivery
|
|
69
|
+
inputs_verified_is_implementation_approval: false
|
|
64
70
|
|
|
65
71
|
compiler_input_required:
|
|
66
72
|
- slice_id
|
|
@@ -77,7 +83,7 @@ exclusive_flags:
|
|
|
77
83
|
|
|
78
84
|
slice_contract_required:
|
|
79
85
|
root: [schema_version, contract_id, contract_version, slice_id, status, lifecycle_refs, readiness, resolution, common, frontend, backend, contract, cross_repo, work_units]
|
|
80
|
-
lifecycle_refs: [spec, ticket, requirement_freeze, low_fidelity_review, prototype_review, prototype_profile_decision, prototype_deliverable, prototype_deliverable_verification, visual_baseline, prototype_confirmation, openapi_freeze_or_no_impact, architecture_review, data_architecture, tactical_design, engineering_baseline, build_architecture_checklist, implementation_repository, frontend_repository, backend_repository, maven_wrapper]
|
|
86
|
+
lifecycle_refs: [spec, ticket, requirement_freeze, low_fidelity_review, prototype_review, prototype_profile_decision, prototype_deliverable, prototype_deliverable_verification, visual_baseline, prototype_confirmation, openapi_freeze_or_no_impact, architecture_review, data_architecture, technical_design, tactical_design, engineering_baseline, build_architecture_checklist, implementation_repository, frontend_repository, backend_repository, maven_wrapper]
|
|
81
87
|
readiness: [blockers, stale_inputs, not_applicable]
|
|
82
88
|
resolution: [required_capabilities, required_skills, recipe_ids, conditions, reason_chains, registry_digest, compiler_contract_digest, compiled_at, freshness]
|
|
83
89
|
common: [impacted_areas, implementation_path_policy, project_roots, required_capabilities, required_skills, optional_skills, unavailable_skills, allowed_write_paths, forbidden_patterns, expected_evidence_files, verification_commands, human_review_points, full_reroute_triggers, quality_baseline_ref, context_plan, doubt_driven_review]
|
|
@@ -103,6 +109,7 @@ lifecycle_ref_by_readiness:
|
|
|
103
109
|
openapi_freeze: openapi_freeze_or_no_impact
|
|
104
110
|
no_api_impact_record: openapi_freeze_or_no_impact
|
|
105
111
|
data_architecture: data_architecture
|
|
112
|
+
technical_design: technical_design
|
|
106
113
|
tactical_design: tactical_design
|
|
107
114
|
engineering_baseline: engineering_baseline
|
|
108
115
|
backend_repository: backend_repository
|
|
@@ -227,7 +234,14 @@ applicable_subcontract_nonempty:
|
|
|
227
234
|
backend:
|
|
228
235
|
scalar: [application_boundary, transaction_boundary, persistence_strategy]
|
|
229
236
|
array: [affected_layers, required_skills, allowed_write_paths, forbidden_patterns, expected_evidence_files, verification_commands]
|
|
237
|
+
conditional_technical_design:
|
|
238
|
+
when: backend-technical-design-impact
|
|
239
|
+
binding: resolution.technical_design
|
|
240
|
+
scalar: [ref, version, digest]
|
|
241
|
+
architecture_match: resolution.architecture_identity.architecture_family
|
|
242
|
+
verification: node .agents/skills/yss-technical-design/scripts/validate-technical-design.mjs <contract> --root <target> --slice <slice-id>
|
|
230
243
|
conditional_tactical_ddd:
|
|
244
|
+
architecture_family: domain-driven
|
|
231
245
|
when: [aggregate-impact, state-machine-impact, invariant-impact, consistency-impact, domain-event-impact, gateway-boundary-impact, persistence-mapping-impact]
|
|
232
246
|
scalar: [tactical_design_ref, tactical_design_version, gateway_boundary_ref]
|
|
233
247
|
array: [aggregate_refs, invariant_refs, state_behavior_refs, domain_test_seams, application_test_seams]
|
|
@@ -360,7 +374,7 @@ unavailable_skill_required: [skill, provider, fallback, resolution]
|
|
|
360
374
|
strategic_handoff_consumption:
|
|
361
375
|
when: upstream-source-is-imported-strategic-handoff
|
|
362
376
|
required: [import_receipt_ref, bundle_digest, context_reconciliation_ref, rows]
|
|
363
|
-
verification: scripts/verify-strategic-handoff-consumption --root <target> --slice <slice-id> <approved-
|
|
377
|
+
verification: scripts/verify-strategic-handoff-consumption --root <target> --slice <slice-id> <approved-technical-design-contract>
|
|
364
378
|
require_actual_exit_code: 0
|
|
365
379
|
stale_policy: latest-imported-source-digest-and-dependent-slices
|
|
366
380
|
unknown_dependency: block-all
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
`yss-implementation-contract-compiler` 生成草案;`yss-product-lifecycle` 核验、批准并持久化。合同缺少必填字段时状态为 `blocked`。schema v1 已停止支持,必须重新编译为 v2,不提供自动升级。
|
|
6
6
|
|
|
7
|
+
采用专职前端 profile 时,`frontend.delivery` 绑定 `{acceptance_ref, digest}`,来自 `scripts/verify-frontend-delivery` 的当前结果;也可由 `resolution.frontend_delivery` 承载,两处并存时必须一致。正式执行从持久化合同读取并重验输入。细则见 `docs/process/frontend-backend-delivery.md`。
|
|
8
|
+
|
|
7
9
|
```yaml
|
|
8
10
|
slice_contract:
|
|
9
11
|
schema_version: 2
|
|
@@ -26,7 +28,8 @@ slice_contract:
|
|
|
26
28
|
architecture_review:
|
|
27
29
|
data_architecture:
|
|
28
30
|
engineering_baseline:
|
|
29
|
-
|
|
31
|
+
technical_design: # 阅读引用;与 resolution.technical_design.ref 指向同一文件
|
|
32
|
+
tactical_design: # 旧 DDD 引用兼容
|
|
30
33
|
build_architecture_checklist:
|
|
31
34
|
implementation_repository:
|
|
32
35
|
frontend_repository:
|
|
@@ -39,6 +42,10 @@ slice_contract:
|
|
|
39
42
|
- item:
|
|
40
43
|
reason:
|
|
41
44
|
resolution:
|
|
45
|
+
technical_design: # 有技术设计影响时由编译器绑定,DDD / MVC 共用
|
|
46
|
+
ref:
|
|
47
|
+
version:
|
|
48
|
+
digest: # 已持久化合同原始字节摘要
|
|
42
49
|
required_capabilities: []
|
|
43
50
|
required_skills: []
|
|
44
51
|
recipe_ids: []
|
|
@@ -199,3 +206,5 @@ work_unit:
|
|
|
199
206
|
`work_units` 中的前端、后端和测试任务是切片级子任务,不是新的生命周期阶段。每个子任务必须引用独立任务包;任务包只能消费同一份已批准且版本当前的 Slice Contract。`workflow_status` 追踪执行过程,不能替代生命周期状态;`contract_id`、`contract_version` 或 resolution digest 不一致时必须阻断并回到实现合同编译器。
|
|
200
207
|
|
|
201
208
|
一个切片可以组合多个窄 Recipe,但只计算一次闭包。Recipe 只能引用 capability;合同同时冻结 `required_capabilities`、`required_skills`、完整原因链和 Registry/Compiler digest。任一 digest 或 Visual Baseline 版本 / digest 改变时,当前合同标记 `stale`,重新编译后仍须由 `yss-product-lifecycle` 再批准。UI 切片只消费 `visual_baseline_case_ids` 指定的图片,并先读取 manifest 与语义引用,禁止按目录 glob 猜测图片含义。
|
|
209
|
+
|
|
210
|
+
技术设计编译绑定使用 `technical_design: {ref, version, digest}` 与 `slice_id`,校验器规则见 `yss-technical-design/references/technical-design-contract.md`。`backend.tactical_ddd` 仅适用于 `domain-driven`;MVC 消费共同技术设计绑定与 `design` 的用例、规则、事务和测试 seam,不填聚合或 Gateway 字段。
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yss-mvc-design
|
|
3
|
+
description: 为已确认 layered-mvc 的 YSS 项目设计分层职责、用例、业务规则、事务和持久化映射,不生成代码。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# YSS MVC 技术设计
|
|
7
|
+
|
|
8
|
+
由 `yss-technical-design` 在 `layered-mvc` 分支调用,输入和批准边界由通用技术设计合同持有。既有工程按已登记 Profile 设计,不重选架构。
|
|
9
|
+
|
|
10
|
+
必须说明模块职责与依赖方向、用例流程、业务规则、状态转换、事务边界、失败回滚、幂等与并发、持久化映射、外部集成与公开测试 seam。无状态流转或外部集成时记录有原因的不适用,不硬造对象。
|
|
11
|
+
|
|
12
|
+
分层边界消费 `docs/agents/backend-architecture-profiles.md`:Controller 处理 HTTP 边界;service/core 承载用例、规则与事务;Repository 负责持久化;适用时 Adapter 承接外部集成。不得为 MVC 加载 `yss-domain` 或生成 DDD Gateway。
|
|
13
|
+
|
|
14
|
+
输出 Technical Design Contract 的 `design` 分支,结构见 `references/mvc-design.schema.json`。业务规则和关键场景必须关联具体用例与测试 seam;关键场景覆盖成功和失败。与 DDD 使用同一承接和审查要求,不能因采用 MVC 省略规则、一致性或测试设计。
|
|
15
|
+
|
|
16
|
+
由通用入口校验整个合同并回交生命周期独立审查。本技能不自行批准、不创建 Ticket、不设置 `ready-for-agent`,不生成 Java、SQL 或生产 API。实现由编译器按批准的架构 Profile 和最小技能闭包路由。
|