create-yss-spec 2.2.2 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -1
- package/package.json +1 -1
- package/src/cli.js +15 -1
- package/src/self-update.js +277 -0
- package/template/.agents/skills/yss-domain/SKILL.md +5 -4
- package/template/.agents/skills/yss-product-lifecycle/SKILL.md +9 -9
- package/template/.agents/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
- package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +8 -5
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +9 -4
- package/template/.agents/skills/yss-router/SKILL.md +5 -3
- package/template/.agents/skills/yss-router/references/router-contract.yaml +18 -3
- package/template/.agents/skills/yss-router/references/slice-implementation-contract.md +59 -1
- package/template/.agents/skills/yss-stage-decision/SKILL.md +50 -0
- package/template/.agents/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
- package/template/.agents/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
- package/template/.agents/skills/yss-stage-decision/references/validation-rules.md +18 -0
- package/template/.agents/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
- package/template/.agents/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
- package/template/.agents/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
- package/template/.agents/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
- package/template/.agents/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
- package/template/.agents/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
- package/template/.agents/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
- package/template/.agents/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
- package/template/.agents/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
- package/template/.agents/skills/yss-tactical-design/SKILL.md +33 -0
- package/template/.agents/skills/yss-tactical-design/agents/openai.yaml +4 -0
- package/template/.agents/skills/yss-tactical-design/references/output-template.md +28 -0
- package/template/.agents/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
- package/template/.agents/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
- package/template/.agents/skills/yss-tactical-design/references/validation-rules.md +13 -0
- package/template/.agents/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
- package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
- package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
- package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
- package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
- package/template/.agents/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
- package/template/.agents/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
- package/template/.agents/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
- package/template/.claude/skills/yss-domain/SKILL.md +5 -4
- package/template/.claude/skills/yss-product-lifecycle/SKILL.md +9 -9
- package/template/.claude/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
- package/template/.claude/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
- package/template/.claude/skills/yss-product-lifecycle/references/orchestration.md +8 -5
- package/template/.claude/skills/yss-product-lifecycle/references/state-model.md +9 -4
- package/template/.claude/skills/yss-router/SKILL.md +5 -3
- package/template/.claude/skills/yss-router/references/router-contract.yaml +18 -3
- package/template/.claude/skills/yss-router/references/slice-implementation-contract.md +59 -1
- package/template/.claude/skills/yss-stage-decision/SKILL.md +50 -0
- package/template/.claude/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
- package/template/.claude/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
- package/template/.claude/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
- package/template/.claude/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
- package/template/.claude/skills/yss-stage-decision/references/validation-rules.md +18 -0
- package/template/.claude/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
- package/template/.claude/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
- package/template/.claude/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
- package/template/.claude/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
- package/template/.claude/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
- package/template/.claude/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
- package/template/.claude/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
- package/template/.claude/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
- package/template/.claude/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
- package/template/.claude/skills/yss-tactical-design/SKILL.md +33 -0
- package/template/.claude/skills/yss-tactical-design/agents/openai.yaml +4 -0
- package/template/.claude/skills/yss-tactical-design/references/output-template.md +28 -0
- package/template/.claude/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
- package/template/.claude/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
- package/template/.claude/skills/yss-tactical-design/references/validation-rules.md +13 -0
- package/template/.claude/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
- package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
- package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
- package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
- package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
- package/template/.claude/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
- package/template/.claude/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
- package/template/.claude/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
- package/template/.codex/skills/yss-domain/SKILL.md +5 -4
- package/template/.codex/skills/yss-product-lifecycle/SKILL.md +9 -9
- package/template/.codex/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
- package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +8 -5
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +9 -4
- package/template/.codex/skills/yss-router/SKILL.md +5 -3
- package/template/.codex/skills/yss-router/references/router-contract.yaml +18 -3
- package/template/.codex/skills/yss-router/references/slice-implementation-contract.md +59 -1
- package/template/.codex/skills/yss-stage-decision/SKILL.md +50 -0
- package/template/.codex/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
- package/template/.codex/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
- package/template/.codex/skills/yss-stage-decision/references/validation-rules.md +18 -0
- package/template/.codex/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
- package/template/.codex/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
- package/template/.codex/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
- package/template/.codex/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
- package/template/.codex/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
- package/template/.codex/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
- package/template/.codex/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
- package/template/.codex/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
- package/template/.codex/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
- package/template/.codex/skills/yss-tactical-design/SKILL.md +33 -0
- package/template/.codex/skills/yss-tactical-design/agents/openai.yaml +4 -0
- package/template/.codex/skills/yss-tactical-design/references/output-template.md +28 -0
- package/template/.codex/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
- package/template/.codex/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
- package/template/.codex/skills/yss-tactical-design/references/validation-rules.md +13 -0
- package/template/.codex/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
- package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
- package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
- package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
- package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
- package/template/.codex/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
- package/template/.codex/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
- package/template/.codex/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
- package/template/.cursor/skills/yss-domain/SKILL.md +5 -4
- package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +9 -9
- package/template/.cursor/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
- package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +8 -5
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +9 -4
- package/template/.cursor/skills/yss-router/SKILL.md +5 -3
- package/template/.cursor/skills/yss-router/references/router-contract.yaml +18 -3
- package/template/.cursor/skills/yss-router/references/slice-implementation-contract.md +59 -1
- package/template/.cursor/skills/yss-stage-decision/SKILL.md +50 -0
- package/template/.cursor/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
- package/template/.cursor/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
- package/template/.cursor/skills/yss-stage-decision/references/validation-rules.md +18 -0
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
- package/template/.cursor/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
- package/template/.cursor/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
- package/template/.cursor/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
- package/template/.cursor/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
- package/template/.cursor/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
- package/template/.cursor/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
- package/template/.cursor/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
- package/template/.cursor/skills/yss-tactical-design/SKILL.md +33 -0
- package/template/.cursor/skills/yss-tactical-design/agents/openai.yaml +4 -0
- package/template/.cursor/skills/yss-tactical-design/references/output-template.md +28 -0
- package/template/.cursor/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
- package/template/.cursor/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
- package/template/.cursor/skills/yss-tactical-design/references/validation-rules.md +13 -0
- package/template/.cursor/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
- package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
- package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
- package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
- package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
- package/template/.cursor/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
- package/template/.cursor/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
- package/template/.cursor/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
- package/template/.hermes/skills/yss-domain/SKILL.md +5 -4
- package/template/.hermes/skills/yss-product-lifecycle/SKILL.md +9 -9
- package/template/.hermes/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
- package/template/.hermes/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.hermes/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
- package/template/.hermes/skills/yss-product-lifecycle/references/orchestration.md +8 -5
- package/template/.hermes/skills/yss-product-lifecycle/references/state-model.md +9 -4
- package/template/.hermes/skills/yss-router/SKILL.md +5 -3
- package/template/.hermes/skills/yss-router/references/router-contract.yaml +18 -3
- package/template/.hermes/skills/yss-router/references/slice-implementation-contract.md +59 -1
- package/template/.hermes/skills/yss-stage-decision/SKILL.md +50 -0
- package/template/.hermes/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
- package/template/.hermes/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
- package/template/.hermes/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
- package/template/.hermes/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
- package/template/.hermes/skills/yss-stage-decision/references/validation-rules.md +18 -0
- package/template/.hermes/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
- package/template/.hermes/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
- package/template/.hermes/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
- package/template/.hermes/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
- package/template/.hermes/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
- package/template/.hermes/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
- package/template/.hermes/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
- package/template/.hermes/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
- package/template/.hermes/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
- package/template/.hermes/skills/yss-tactical-design/SKILL.md +33 -0
- package/template/.hermes/skills/yss-tactical-design/agents/openai.yaml +4 -0
- package/template/.hermes/skills/yss-tactical-design/references/output-template.md +28 -0
- package/template/.hermes/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
- package/template/.hermes/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
- package/template/.hermes/skills/yss-tactical-design/references/validation-rules.md +13 -0
- package/template/.hermes/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
- package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
- package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
- package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
- package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
- package/template/.hermes/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
- package/template/.hermes/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
- package/template/.hermes/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
- package/template/.pi/skills/yss-domain/SKILL.md +5 -4
- package/template/.pi/skills/yss-product-lifecycle/SKILL.md +9 -9
- package/template/.pi/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
- package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +8 -5
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +9 -4
- package/template/.pi/skills/yss-router/SKILL.md +5 -3
- package/template/.pi/skills/yss-router/references/router-contract.yaml +18 -3
- package/template/.pi/skills/yss-router/references/slice-implementation-contract.md +59 -1
- package/template/.pi/skills/yss-stage-decision/SKILL.md +50 -0
- package/template/.pi/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
- package/template/.pi/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
- package/template/.pi/skills/yss-stage-decision/references/validation-rules.md +18 -0
- package/template/.pi/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
- package/template/.pi/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
- package/template/.pi/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
- package/template/.pi/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
- package/template/.pi/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
- package/template/.pi/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
- package/template/.pi/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
- package/template/.pi/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
- package/template/.pi/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
- package/template/.pi/skills/yss-tactical-design/SKILL.md +33 -0
- package/template/.pi/skills/yss-tactical-design/agents/openai.yaml +4 -0
- package/template/.pi/skills/yss-tactical-design/references/output-template.md +28 -0
- package/template/.pi/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
- package/template/.pi/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
- package/template/.pi/skills/yss-tactical-design/references/validation-rules.md +13 -0
- package/template/.pi/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
- package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
- package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
- package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
- package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
- package/template/.pi/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
- package/template/.pi/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
- package/template/.pi/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
- package/template/.qoder/skills/yss-domain/SKILL.md +5 -4
- package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +9 -9
- package/template/.qoder/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
- package/template/.qoder/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
- package/template/.qoder/skills/yss-product-lifecycle/references/orchestration.md +8 -5
- package/template/.qoder/skills/yss-product-lifecycle/references/state-model.md +9 -4
- package/template/.qoder/skills/yss-router/SKILL.md +5 -3
- package/template/.qoder/skills/yss-router/references/router-contract.yaml +18 -3
- package/template/.qoder/skills/yss-router/references/slice-implementation-contract.md +59 -1
- package/template/.qoder/skills/yss-stage-decision/SKILL.md +50 -0
- package/template/.qoder/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
- package/template/.qoder/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
- package/template/.qoder/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
- package/template/.qoder/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
- package/template/.qoder/skills/yss-stage-decision/references/validation-rules.md +18 -0
- package/template/.qoder/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
- package/template/.qoder/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
- package/template/.qoder/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
- package/template/.qoder/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
- package/template/.qoder/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
- package/template/.qoder/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
- package/template/.qoder/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
- package/template/.qoder/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
- package/template/.qoder/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
- package/template/.qoder/skills/yss-tactical-design/SKILL.md +33 -0
- package/template/.qoder/skills/yss-tactical-design/agents/openai.yaml +4 -0
- package/template/.qoder/skills/yss-tactical-design/references/output-template.md +28 -0
- package/template/.qoder/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
- package/template/.qoder/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
- package/template/.qoder/skills/yss-tactical-design/references/validation-rules.md +13 -0
- package/template/.qoder/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
- package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
- package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
- package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
- package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
- package/template/.qoder/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
- package/template/.qoder/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
- package/template/.qoder/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
- package/template/.trae/skills/yss-domain/SKILL.md +5 -4
- package/template/.trae/skills/yss-product-lifecycle/SKILL.md +9 -9
- package/template/.trae/skills/yss-product-lifecycle/references/artifact-dependencies.md +4 -0
- package/template/.trae/skills/yss-product-lifecycle/references/matt-yss-adapter.md +3 -3
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration-contract.yaml +139 -4
- package/template/.trae/skills/yss-product-lifecycle/references/orchestration.md +8 -5
- package/template/.trae/skills/yss-product-lifecycle/references/state-model.md +9 -4
- package/template/.trae/skills/yss-router/SKILL.md +5 -3
- package/template/.trae/skills/yss-router/references/router-contract.yaml +18 -3
- package/template/.trae/skills/yss-router/references/slice-implementation-contract.md +59 -1
- package/template/.trae/skills/yss-stage-decision/SKILL.md +50 -0
- package/template/.trae/skills/yss-stage-decision/references/domain-strategy-contract.md +26 -0
- package/template/.trae/skills/yss-stage-decision/references/domain-strategy.schema.json +128 -0
- package/template/.trae/skills/yss-stage-decision/references/stage-decision-package-contract.md +19 -0
- package/template/.trae/skills/yss-stage-decision/references/stage-decision-package.schema.json +86 -0
- package/template/.trae/skills/yss-stage-decision/references/validation-rules.md +18 -0
- package/template/.trae/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +169 -0
- package/template/.trae/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +100 -0
- package/template/.trae/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml +15 -0
- package/template/.trae/skills/yss-stage-decision/tests/fixtures/invalid-direction.yaml +58 -0
- package/template/.trae/skills/yss-stage-decision/tests/fixtures/invalid-stage-decision-blocker.yaml +44 -0
- package/template/.trae/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml +15 -0
- package/template/.trae/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +49 -0
- package/template/.trae/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +108 -0
- package/template/.trae/skills/yss-stage-decision/tests/run-scenarios.mjs +68 -0
- package/template/.trae/skills/yss-tactical-design/SKILL.md +33 -0
- package/template/.trae/skills/yss-tactical-design/agents/openai.yaml +4 -0
- package/template/.trae/skills/yss-tactical-design/references/output-template.md +28 -0
- package/template/.trae/skills/yss-tactical-design/references/tactical-design-contract.md +41 -0
- package/template/.trae/skills/yss-tactical-design/references/tactical-design.schema.json +31 -0
- package/template/.trae/skills/yss-tactical-design/references/validation-rules.md +13 -0
- package/template/.trae/skills/yss-tactical-design/scripts/validate-tactical-design.mjs +213 -0
- package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml +21 -0
- package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-missing-consistency-policy.yaml +21 -0
- package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml +21 -0
- package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml +21 -0
- package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml +21 -0
- package/template/.trae/skills/yss-tactical-design/tests/fixtures/valid-tactical-design.yaml +80 -0
- package/template/.trae/skills/yss-tactical-design/tests/run-scenarios.mjs +47 -0
- package/template/AGENTS.md +8 -4
- package/template/CONTEXT.md +14 -2
- package/template/docs/agents/digital-human-roles.md +83 -0
- package/template/docs/agents/digital-human-roles.yaml +259 -0
- package/template/docs/agents/triage-labels.md +5 -5
- package/template/docs/agents/yss-skill-registry.yaml +12 -0
- package/template/docs/architecture/templates/system-overview-design-template.md +1 -0
- package/template/docs/process/lifecycle-artifact-map.md +8 -0
- package/template/docs/process/lifecycle-registry-baseline.json +11 -1
- package/template/docs/process/lifecycle-registry.yaml +46 -2
- package/template/docs/process/schemas/digital-human-task-package.schema.json +107 -0
- package/template/docs/process/schemas/lifecycle-checkpoint.schema.json +2 -1
- package/template/docs/process/schemas/subagent-task-package.schema.json +6 -0
- package/template/docs/process/subagent-collaboration.md +5 -3
- package/template/docs/process/templates/stage-checkpoint-template.md +3 -1
- package/template/docs/templates/approval-record-template.yaml +14 -0
- package/template/docs/templates/digital-human-runtime-profile-template.md +38 -0
- package/template/docs/templates/grok-bot-profile-template.md +24 -0
- package/template/docs/templates/implementation-routing-template.md +3 -3
- package/template/docs/templates/local-parent-ticket-template.md +8 -0
- package/template/docs/templates/subagent-task-package-template.md +43 -1
- package/template/docs/templates/vertical-slice-ticket-template.md +7 -0
- package/template/docs/user-guide//344/272/247/345/223/201/347/240/224/345/217/221/345/205/250/347/224/237/345/221/275/345/221/250/346/234/237/346/234/200/344/275/263/345/256/236/350/267/265.md +2 -0
- package/template/scripts/lib/approval-record.mjs +123 -0
- package/template/scripts/lib/digital-human-roles.mjs +398 -0
- package/template/scripts/lib/lifecycle-transition.mjs +259 -0
- package/template/scripts/lib/scenario-checks.mjs +96 -2
- package/template/scripts/lib/task-package.mjs +214 -0
- package/template/scripts/verify-approval-record +13 -0
- package/template/scripts/verify-digital-human-roles +10 -0
- package/template/scripts/verify-digital-human-roles-scenarios +147 -0
- package/template/scripts/verify-digital-human-task-package +14 -0
- package/template/scripts/verify-digital-human-task-package-scenarios +8 -0
- package/template/scripts/verify-lifecycle-checkpoint +2 -0
- package/template/scripts/verify-lifecycle-transition-scenarios +105 -0
- package/template/scripts/verify-subagent-task-package +8 -0
- package/template/scripts/verify-subagent-task-package-scenarios +196 -0
- package/template/scripts/verify-template +16 -2
- package/template/skills-lock.json +35 -3
- package/template.snapshot.json +4 -4
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
|
|
5
|
+
|
|
6
|
+
const required = [
|
|
7
|
+
"schema_version", "tactical_design_id", "tactical_version", "status", "context_ref",
|
|
8
|
+
"aggregate_catalog", "entity_catalog", "value_object_catalog", "behavior_catalog",
|
|
9
|
+
"invariant_catalog", "state_transition_catalog", "consistency_policy", "domain_event_catalog",
|
|
10
|
+
"gateway_catalog", "persistence_mapping", "test_seams", "adr_candidates", "upstream_impact",
|
|
11
|
+
"version", "digest", "evidence_refs"
|
|
12
|
+
];
|
|
13
|
+
const statuses = new Set(["draft", "ready-for-human", "approved", "blocked", "stale", "drift", "new_impacts", "not-applicable"]);
|
|
14
|
+
const idPatterns = {
|
|
15
|
+
tactical_design_id: /^tactical-design\.[a-z0-9][a-z0-9-]*$/,
|
|
16
|
+
aggregate_id: /^aggregate\.[a-z0-9][a-z0-9-]*$/,
|
|
17
|
+
entity_id: /^entity\.[a-z0-9][a-z0-9-]*$/,
|
|
18
|
+
value_object_id: /^value-object\.[a-z0-9][a-z0-9-]*$/,
|
|
19
|
+
behavior_id: /^behavior\.[a-z0-9][a-z0-9-]*$/,
|
|
20
|
+
invariant_id: /^invariant\.[a-z0-9][a-z0-9-]*$/,
|
|
21
|
+
transition_id: /^transition\.[a-z0-9][a-z0-9-]*$/,
|
|
22
|
+
event_id: /^domain-event\.[a-z0-9][a-z0-9-]*$/,
|
|
23
|
+
gateway_id: /^gateway\.[a-z0-9][a-z0-9-]*$/,
|
|
24
|
+
seam_id: /^test-seam\.[a-z0-9][a-z0-9-]*$/,
|
|
25
|
+
version: /^v[0-9]+$/
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const isObject = (value) => value && typeof value === "object" && !Array.isArray(value);
|
|
29
|
+
const nonEmpty = (value) => typeof value === "string" && value.trim().length > 0;
|
|
30
|
+
const list = (value) => Array.isArray(value);
|
|
31
|
+
|
|
32
|
+
function unique(items, label, errors) {
|
|
33
|
+
const seen = new Set();
|
|
34
|
+
for (const item of items) {
|
|
35
|
+
if (seen.has(item)) errors.push(`${label} 重复: ${item}`);
|
|
36
|
+
seen.add(item);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function requireField(object, field, path, errors) {
|
|
41
|
+
if (!Object.prototype.hasOwnProperty.call(object ?? {}, field) || object[field] === null || object[field] === undefined) {
|
|
42
|
+
errors.push(`${path}.${field} 缺失`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function requireString(object, field, path, errors) {
|
|
47
|
+
requireField(object, field, path, errors);
|
|
48
|
+
if (Object.prototype.hasOwnProperty.call(object ?? {}, field) && !nonEmpty(object[field])) errors.push(`${path}.${field} 必须是非空字符串`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function requireArray(object, field, path, errors, minimum = 0) {
|
|
52
|
+
requireField(object, field, path, errors);
|
|
53
|
+
if (Object.prototype.hasOwnProperty.call(object ?? {}, field) && (!list(object[field]) || object[field].length < minimum)) {
|
|
54
|
+
errors.push(`${path}.${field} 必须是至少 ${minimum} 项的数组`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function requireId(value, kind, path, errors) {
|
|
59
|
+
if (value !== undefined && value !== null && !idPatterns[kind].test(String(value))) errors.push(`${path} 格式非法`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function refsExist(values, known, path, errors) {
|
|
63
|
+
for (const [index, value] of (values ?? []).entries()) {
|
|
64
|
+
if (!known.has(value)) errors.push(`${path}[${index}] 引用了未声明对象: ${value}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function validate(data) {
|
|
69
|
+
const errors = [];
|
|
70
|
+
if (!isObject(data)) return ["合同必须是对象"];
|
|
71
|
+
for (const field of required) requireField(data, field, "root", errors);
|
|
72
|
+
if (data.schema_version !== 1) errors.push("schema_version 必须为 1");
|
|
73
|
+
requireId(data.tactical_design_id, "tactical_design_id", "tactical_design_id", errors);
|
|
74
|
+
for (const field of ["tactical_version", "version"]) if (data[field] !== undefined && !idPatterns.version.test(String(data[field]))) errors.push(`${field} 必须形如 v1`);
|
|
75
|
+
if (data.status !== undefined && !statuses.has(data.status)) errors.push(`status 非法: ${data.status}`);
|
|
76
|
+
if (data.digest !== undefined && !/^sha256:[A-Fa-f0-9]{64}$/.test(String(data.digest))) errors.push("digest 必须为 sha256 加 64 位十六进制");
|
|
77
|
+
|
|
78
|
+
for (const field of ["aggregate_catalog", "entity_catalog", "behavior_catalog", "invariant_catalog", "state_transition_catalog", "gateway_catalog", "persistence_mapping", "test_seams"]) {
|
|
79
|
+
requireArray(data, field, "root", errors, 1);
|
|
80
|
+
}
|
|
81
|
+
for (const field of ["value_object_catalog", "domain_event_catalog", "adr_candidates", "evidence_refs"]) requireArray(data, field, "root", errors);
|
|
82
|
+
if (!isObject(data.consistency_policy)) errors.push("consistency_policy 必须是对象");
|
|
83
|
+
if (!isObject(data.upstream_impact)) errors.push("upstream_impact 必须是对象");
|
|
84
|
+
if (isObject(data.consistency_policy)) {
|
|
85
|
+
for (const field of ["transaction_boundary", "concurrency", "idempotency", "cross_aggregate_strategy"]) requireString(data.consistency_policy, field, "consistency_policy", errors);
|
|
86
|
+
}
|
|
87
|
+
if (isObject(data.upstream_impact)) {
|
|
88
|
+
for (const field of ["spec_ref", "strategic_ref", "api_ref", "data_ref"]) requireString(data.upstream_impact, field, "upstream_impact", errors);
|
|
89
|
+
if (data.upstream_impact.upstream_current === false && data.status !== "stale") errors.push("上游已过期时 status 必须为 stale");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const aggregates = list(data.aggregate_catalog) ? data.aggregate_catalog : [];
|
|
93
|
+
const entities = list(data.entity_catalog) ? data.entity_catalog : [];
|
|
94
|
+
const values = list(data.value_object_catalog) ? data.value_object_catalog : [];
|
|
95
|
+
const behaviors = list(data.behavior_catalog) ? data.behavior_catalog : [];
|
|
96
|
+
const invariants = list(data.invariant_catalog) ? data.invariant_catalog : [];
|
|
97
|
+
const transitions = list(data.state_transition_catalog) ? data.state_transition_catalog : [];
|
|
98
|
+
const events = list(data.domain_event_catalog) ? data.domain_event_catalog : [];
|
|
99
|
+
const gateways = list(data.gateway_catalog) ? data.gateway_catalog : [];
|
|
100
|
+
const mappings = list(data.persistence_mapping) ? data.persistence_mapping : [];
|
|
101
|
+
const seams = list(data.test_seams) ? data.test_seams : [];
|
|
102
|
+
const ids = (items, field, kind, label) => {
|
|
103
|
+
const result = new Set();
|
|
104
|
+
unique(items.map((item) => item?.[field]).filter(Boolean), label, errors);
|
|
105
|
+
for (const [index, item] of items.entries()) {
|
|
106
|
+
if (item?.[field]) { requireId(item[field], kind, `${label}[${index}].${field}`, errors); result.add(item[field]); }
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
};
|
|
110
|
+
const aggregateIds = ids(aggregates, "aggregate_id", "aggregate_id", "aggregate_id");
|
|
111
|
+
const entityIds = ids(entities, "entity_id", "entity_id", "entity_id");
|
|
112
|
+
const valueIds = ids(values, "value_object_id", "value_object_id", "value_object_id");
|
|
113
|
+
const behaviorIds = ids(behaviors, "behavior_id", "behavior_id", "behavior_id");
|
|
114
|
+
const invariantIds = ids(invariants, "invariant_id", "invariant_id", "invariant_id");
|
|
115
|
+
const transitionIds = ids(transitions, "transition_id", "transition_id", "transition_id");
|
|
116
|
+
const eventIds = ids(events, "event_id", "event_id", "event_id");
|
|
117
|
+
const gatewayIds = ids(gateways, "gateway_id", "gateway_id", "gateway_id");
|
|
118
|
+
ids(seams, "seam_id", "seam_id", "seam_id");
|
|
119
|
+
|
|
120
|
+
for (const [index, aggregate] of aggregates.entries()) {
|
|
121
|
+
const path = `aggregate_catalog[${index}]`;
|
|
122
|
+
if (!isObject(aggregate)) { errors.push(`${path} 必须是对象`); continue; }
|
|
123
|
+
for (const field of ["aggregate_id", "name", "context_ref", "root_entity", "consistency_boundary"]) requireString(aggregate, field, path, errors);
|
|
124
|
+
requireArray(aggregate, "invariant_refs", path, errors, 1); requireArray(aggregate, "behavior_refs", path, errors, 1);
|
|
125
|
+
if (aggregate.model_origin === "strategic-concept") errors.push(`${path}.model_origin 不得直接把战略概念当作 Aggregate`);
|
|
126
|
+
if (aggregate.api_exposure !== "internal-only") errors.push(`${path}.api_exposure 必须为 internal-only`);
|
|
127
|
+
if (aggregate.root_entity && !entityIds.has(aggregate.root_entity)) errors.push(`${path}.root_entity 未引用 Entity`);
|
|
128
|
+
const rootEntity = entities.find((entity) => entity?.entity_id === aggregate.root_entity);
|
|
129
|
+
if (rootEntity && rootEntity.aggregate_id !== aggregate.aggregate_id) errors.push(`${path}.root_entity 的 aggregate_id 必须与当前 Aggregate 一致`);
|
|
130
|
+
refsExist(aggregate.invariant_refs, invariantIds, `${path}.invariant_refs`, errors);
|
|
131
|
+
refsExist(aggregate.behavior_refs, behaviorIds, `${path}.behavior_refs`, errors);
|
|
132
|
+
}
|
|
133
|
+
for (const [index, entity] of entities.entries()) {
|
|
134
|
+
const path = `entity_catalog[${index}]`;
|
|
135
|
+
if (!isObject(entity)) { errors.push(`${path} 必须是对象`); continue; }
|
|
136
|
+
for (const field of ["entity_id", "name", "aggregate_id", "identity", "lifecycle"]) requireString(entity, field, path, errors);
|
|
137
|
+
if (entity.aggregate_id && !aggregateIds.has(entity.aggregate_id)) errors.push(`${path}.aggregate_id 未引用 Aggregate`);
|
|
138
|
+
}
|
|
139
|
+
for (const [index, value] of values.entries()) {
|
|
140
|
+
const path = `value_object_catalog[${index}]`;
|
|
141
|
+
if (!isObject(value)) { errors.push(`${path} 必须是对象`); continue; }
|
|
142
|
+
for (const field of ["value_object_id", "name", "aggregate_id", "immutable"]) requireField(value, field, path, errors);
|
|
143
|
+
if (typeof value.immutable !== "boolean" || value.immutable !== true) errors.push(`${path}.immutable 必须为 true`);
|
|
144
|
+
if (value.aggregate_id && !aggregateIds.has(value.aggregate_id)) errors.push(`${path}.aggregate_id 未引用 Aggregate`);
|
|
145
|
+
}
|
|
146
|
+
for (const [index, behavior] of behaviors.entries()) {
|
|
147
|
+
const path = `behavior_catalog[${index}]`;
|
|
148
|
+
if (!isObject(behavior)) { errors.push(`${path} 必须是对象`); continue; }
|
|
149
|
+
for (const field of ["behavior_id", "name", "aggregate_id", "command"]) requireString(behavior, field, path, errors);
|
|
150
|
+
for (const field of ["preconditions", "invariant_refs", "postconditions", "event_refs"]) requireArray(behavior, field, path, errors, field === "invariant_refs" ? 1 : 0);
|
|
151
|
+
if (behavior.aggregate_id && !aggregateIds.has(behavior.aggregate_id)) errors.push(`${path}.aggregate_id 未引用 Aggregate`);
|
|
152
|
+
refsExist(behavior.invariant_refs, invariantIds, `${path}.invariant_refs`, errors);
|
|
153
|
+
refsExist(behavior.event_refs, eventIds, `${path}.event_refs`, errors);
|
|
154
|
+
}
|
|
155
|
+
for (const [index, invariant] of invariants.entries()) {
|
|
156
|
+
const path = `invariant_catalog[${index}]`;
|
|
157
|
+
if (!isObject(invariant)) { errors.push(`${path} 必须是对象`); continue; }
|
|
158
|
+
for (const field of ["invariant_id", "aggregate_id", "statement"]) requireString(invariant, field, path, errors);
|
|
159
|
+
if (invariant.aggregate_id && !aggregateIds.has(invariant.aggregate_id)) errors.push(`${path}.aggregate_id 未引用 Aggregate`);
|
|
160
|
+
}
|
|
161
|
+
for (const [index, transition] of transitions.entries()) {
|
|
162
|
+
const path = `state_transition_catalog[${index}]`;
|
|
163
|
+
if (!isObject(transition)) { errors.push(`${path} 必须是对象`); continue; }
|
|
164
|
+
for (const field of ["transition_id", "aggregate_id", "from", "to", "behavior_id"]) requireString(transition, field, path, errors);
|
|
165
|
+
if (transition.aggregate_id && !aggregateIds.has(transition.aggregate_id)) errors.push(`${path}.aggregate_id 未引用 Aggregate`);
|
|
166
|
+
if (transition.behavior_id && !behaviorIds.has(transition.behavior_id)) errors.push(`${path}.behavior_id 未引用行为`);
|
|
167
|
+
}
|
|
168
|
+
for (const [index, event] of events.entries()) {
|
|
169
|
+
const path = `domain_event_catalog[${index}]`;
|
|
170
|
+
if (!isObject(event)) { errors.push(`${path} 必须是对象`); continue; }
|
|
171
|
+
for (const field of ["event_id", "name", "aggregate_id", "delivery"]) requireString(event, field, path, errors);
|
|
172
|
+
requireArray(event, "consumers", path, errors, 0);
|
|
173
|
+
if (event.aggregate_id && !aggregateIds.has(event.aggregate_id)) errors.push(`${path}.aggregate_id 未引用 Aggregate`);
|
|
174
|
+
}
|
|
175
|
+
for (const [index, gateway] of gateways.entries()) {
|
|
176
|
+
const path = `gateway_catalog[${index}]`;
|
|
177
|
+
if (!isObject(gateway)) { errors.push(`${path} 必须是对象`); continue; }
|
|
178
|
+
for (const field of ["gateway_id", "name", "context_ref", "layer"]) requireString(gateway, field, path, errors);
|
|
179
|
+
requireArray(gateway, "capabilities", path, errors, 1);
|
|
180
|
+
if (gateway.layer !== "Domain") errors.push(`${path}.layer 必须为 Domain,Infrastructure 只实现 Gateway`);
|
|
181
|
+
}
|
|
182
|
+
for (const [index, mapping] of mappings.entries()) {
|
|
183
|
+
const path = `persistence_mapping[${index}]`;
|
|
184
|
+
if (!isObject(mapping)) { errors.push(`${path} 必须是对象`); continue; }
|
|
185
|
+
for (const field of ["aggregate_id", "storage_model", "notes"]) requireString(mapping, field, path, errors);
|
|
186
|
+
if (mapping.aggregate_id && !aggregateIds.has(mapping.aggregate_id)) errors.push(`${path}.aggregate_id 未引用 Aggregate`);
|
|
187
|
+
}
|
|
188
|
+
for (const [index, seam] of seams.entries()) {
|
|
189
|
+
const path = `test_seams[${index}]`;
|
|
190
|
+
if (!isObject(seam)) { errors.push(`${path} 必须是对象`); continue; }
|
|
191
|
+
for (const field of ["seam_id", "kind", "subject_ref", "assertion"]) requireString(seam, field, path, errors);
|
|
192
|
+
if (seam.subject_ref && !new Set([...aggregateIds, ...entityIds, ...valueIds, ...behaviorIds, ...invariantIds, ...transitionIds, ...gatewayIds]).has(seam.subject_ref)) errors.push(`${path}.subject_ref 未引用已声明领域对象`);
|
|
193
|
+
}
|
|
194
|
+
if (isObject(data.complexity) && data.complexity.escalate_to_standalone === true && !nonEmpty(data.complexity.standalone_ref)) errors.push("complexity.escalate_to_standalone 为 true 时必须提供 standalone_ref");
|
|
195
|
+
return errors;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function main() {
|
|
199
|
+
const file = process.argv[2];
|
|
200
|
+
if (!file) throw new Error("用法: validate-tactical-design.mjs <contract.yaml>");
|
|
201
|
+
const source = await readFile(file, "utf8");
|
|
202
|
+
const document = parseDocument(source, { maxAliasCount: 0, uniqueKeys: true });
|
|
203
|
+
if (document.errors.length) throw new Error(`无法解析合同: ${document.errors[0].message}`);
|
|
204
|
+
const errors = validate(document.toJS({ maxAliasCount: 0 }));
|
|
205
|
+
if (errors.length) {
|
|
206
|
+
process.stderr.write(`${JSON.stringify({ result: "blocked", errors }, null, 2)}\n`);
|
|
207
|
+
process.exitCode = 1;
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
process.stdout.write(`${JSON.stringify({ result: "ready-for-lifecycle-review", tactical_design_id: document.get("tactical_design_id"), status: document.get("status") }, null, 2)}\n`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
main().catch((error) => { process.stderr.write(`${error.message}\n`); process.exitCode = 1; });
|
package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-api-leaks-aggregate.yaml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
tactical_design_id: tactical-design.invalid-api
|
|
3
|
+
tactical_version: v1
|
|
4
|
+
status: ready-for-human
|
|
5
|
+
context_ref: context.example
|
|
6
|
+
aggregate_catalog: [{aggregate_id: aggregate.example, name: Example, context_ref: context.example, root_entity: entity.example-root, invariant_refs: [invariant.example], behavior_refs: [behavior.example], consistency_boundary: single, api_exposure: public-aggregate}]
|
|
7
|
+
entity_catalog: [{entity_id: entity.example-root, name: Root, aggregate_id: aggregate.example, identity: id, lifecycle: active}]
|
|
8
|
+
value_object_catalog: []
|
|
9
|
+
behavior_catalog: [{behavior_id: behavior.example, name: Do, aggregate_id: aggregate.example, command: do, preconditions: [ready], invariant_refs: [invariant.example], postconditions: [done], event_refs: []}]
|
|
10
|
+
invariant_catalog: [{invariant_id: invariant.example, aggregate_id: aggregate.example, statement: required}]
|
|
11
|
+
state_transition_catalog: [{transition_id: transition.example, aggregate_id: aggregate.example, from: draft, to: done, behavior_id: behavior.example}]
|
|
12
|
+
consistency_policy: {transaction_boundary: single, concurrency: optimistic, idempotency: guarded, cross_aggregate_strategy: none}
|
|
13
|
+
domain_event_catalog: []
|
|
14
|
+
gateway_catalog: [{gateway_id: gateway.example, name: Gateway, context_ref: context.example, layer: Domain, capabilities: [load]}]
|
|
15
|
+
persistence_mapping: [{aggregate_id: aggregate.example, storage_model: example, notes: mapping}]
|
|
16
|
+
test_seams: [{seam_id: test-seam.example, kind: domain, subject_ref: invariant.example, assertion: behavior}]
|
|
17
|
+
adr_candidates: []
|
|
18
|
+
upstream_impact: {spec_ref: spec@v1, strategic_ref: strategy@v1, api_ref: api@draft, data_ref: data@v1, upstream_current: true}
|
|
19
|
+
version: v1
|
|
20
|
+
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
21
|
+
evidence_refs: []
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
tactical_design_id: tactical-design.invalid-consistency
|
|
3
|
+
tactical_version: v1
|
|
4
|
+
status: ready-for-human
|
|
5
|
+
context_ref: context.example
|
|
6
|
+
aggregate_catalog: [{aggregate_id: aggregate.example, name: Example, context_ref: context.example, root_entity: entity.example-root, invariant_refs: [invariant.example], behavior_refs: [behavior.example], consistency_boundary: single, api_exposure: internal-only}]
|
|
7
|
+
entity_catalog: [{entity_id: entity.example-root, name: Root, aggregate_id: aggregate.example, identity: id, lifecycle: active}]
|
|
8
|
+
value_object_catalog: []
|
|
9
|
+
behavior_catalog: [{behavior_id: behavior.example, name: Do, aggregate_id: aggregate.example, command: do, preconditions: [ready], invariant_refs: [invariant.example], postconditions: [done], event_refs: []}]
|
|
10
|
+
invariant_catalog: [{invariant_id: invariant.example, aggregate_id: aggregate.example, statement: required}]
|
|
11
|
+
state_transition_catalog: [{transition_id: transition.example, aggregate_id: aggregate.example, from: draft, to: done, behavior_id: behavior.example}]
|
|
12
|
+
consistency_policy: {}
|
|
13
|
+
domain_event_catalog: []
|
|
14
|
+
gateway_catalog: [{gateway_id: gateway.example, name: Gateway, context_ref: context.example, layer: Domain, capabilities: [load]}]
|
|
15
|
+
persistence_mapping: [{aggregate_id: aggregate.example, storage_model: example, notes: mapping}]
|
|
16
|
+
test_seams: [{seam_id: test-seam.example, kind: domain, subject_ref: invariant.example, assertion: behavior}]
|
|
17
|
+
adr_candidates: []
|
|
18
|
+
upstream_impact: {spec_ref: spec@v1, strategic_ref: strategy@v1, api_ref: api@draft, data_ref: data@v1, upstream_current: true}
|
|
19
|
+
version: v1
|
|
20
|
+
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
21
|
+
evidence_refs: []
|
package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-missing-invariant.yaml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
tactical_design_id: tactical-design.invalid-missing-invariant
|
|
3
|
+
tactical_version: v1
|
|
4
|
+
status: ready-for-human
|
|
5
|
+
context_ref: context.example
|
|
6
|
+
aggregate_catalog: [{aggregate_id: aggregate.example, name: Example, context_ref: context.example, root_entity: entity.example-root, invariant_refs: [], behavior_refs: [behavior.example], consistency_boundary: single, api_exposure: internal-only}]
|
|
7
|
+
entity_catalog: [{entity_id: entity.example-root, name: Root, aggregate_id: aggregate.example, identity: id, lifecycle: active}]
|
|
8
|
+
value_object_catalog: []
|
|
9
|
+
behavior_catalog: [{behavior_id: behavior.example, name: Do, aggregate_id: aggregate.example, command: do, preconditions: [], invariant_refs: [], postconditions: [], event_refs: []}]
|
|
10
|
+
invariant_catalog: []
|
|
11
|
+
state_transition_catalog: [{transition_id: transition.example, aggregate_id: aggregate.example, from: draft, to: done, behavior_id: behavior.example}]
|
|
12
|
+
consistency_policy: {transaction_boundary: single, concurrency: optimistic, idempotency: guarded, cross_aggregate_strategy: none}
|
|
13
|
+
domain_event_catalog: []
|
|
14
|
+
gateway_catalog: [{gateway_id: gateway.example, name: Gateway, context_ref: context.example, layer: Domain, capabilities: [load]}]
|
|
15
|
+
persistence_mapping: [{aggregate_id: aggregate.example, storage_model: example, notes: mapping}]
|
|
16
|
+
test_seams: [{seam_id: test-seam.example, kind: domain, subject_ref: aggregate.example, assertion: behavior}]
|
|
17
|
+
adr_candidates: []
|
|
18
|
+
upstream_impact: {spec_ref: spec@v1, strategic_ref: strategy@v1, api_ref: api@draft, data_ref: data@v1, upstream_current: true}
|
|
19
|
+
version: v1
|
|
20
|
+
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
21
|
+
evidence_refs: []
|
package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-stale-upstream-ref.yaml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
tactical_design_id: tactical-design.invalid-stale
|
|
3
|
+
tactical_version: v1
|
|
4
|
+
status: ready-for-human
|
|
5
|
+
context_ref: context.example
|
|
6
|
+
aggregate_catalog: [{aggregate_id: aggregate.example, name: Example, context_ref: context.example, root_entity: entity.example-root, invariant_refs: [invariant.example], behavior_refs: [behavior.example], consistency_boundary: single, api_exposure: internal-only}]
|
|
7
|
+
entity_catalog: [{entity_id: entity.example-root, name: Root, aggregate_id: aggregate.example, identity: id, lifecycle: active}]
|
|
8
|
+
value_object_catalog: []
|
|
9
|
+
behavior_catalog: [{behavior_id: behavior.example, name: Do, aggregate_id: aggregate.example, command: do, preconditions: [ready], invariant_refs: [invariant.example], postconditions: [done], event_refs: []}]
|
|
10
|
+
invariant_catalog: [{invariant_id: invariant.example, aggregate_id: aggregate.example, statement: required}]
|
|
11
|
+
state_transition_catalog: [{transition_id: transition.example, aggregate_id: aggregate.example, from: draft, to: done, behavior_id: behavior.example}]
|
|
12
|
+
consistency_policy: {transaction_boundary: single, concurrency: optimistic, idempotency: guarded, cross_aggregate_strategy: none}
|
|
13
|
+
domain_event_catalog: []
|
|
14
|
+
gateway_catalog: [{gateway_id: gateway.example, name: Gateway, context_ref: context.example, layer: Domain, capabilities: [load]}]
|
|
15
|
+
persistence_mapping: [{aggregate_id: aggregate.example, storage_model: example, notes: mapping}]
|
|
16
|
+
test_seams: [{seam_id: test-seam.example, kind: domain, subject_ref: invariant.example, assertion: behavior}]
|
|
17
|
+
adr_candidates: []
|
|
18
|
+
upstream_impact: {spec_ref: spec@v1, strategic_ref: strategy@v1, api_ref: api@draft, data_ref: data@v1, upstream_current: false}
|
|
19
|
+
version: v1
|
|
20
|
+
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
21
|
+
evidence_refs: []
|
package/template/.trae/skills/yss-tactical-design/tests/fixtures/invalid-strategic-as-tactical.yaml
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
tactical_design_id: tactical-design.invalid-strategic
|
|
3
|
+
tactical_version: v1
|
|
4
|
+
status: ready-for-human
|
|
5
|
+
context_ref: context.example
|
|
6
|
+
aggregate_catalog: [{aggregate_id: aggregate.example, name: Example, context_ref: context.example, root_entity: entity.example-root, model_origin: strategic-concept, invariant_refs: [invariant.example], behavior_refs: [behavior.example], consistency_boundary: single, api_exposure: internal-only}]
|
|
7
|
+
entity_catalog: [{entity_id: entity.example-root, name: Root, aggregate_id: aggregate.example, identity: id, lifecycle: active}]
|
|
8
|
+
value_object_catalog: []
|
|
9
|
+
behavior_catalog: [{behavior_id: behavior.example, name: Do, aggregate_id: aggregate.example, command: do, preconditions: [ready], invariant_refs: [invariant.example], postconditions: [done], event_refs: []}]
|
|
10
|
+
invariant_catalog: [{invariant_id: invariant.example, aggregate_id: aggregate.example, statement: required}]
|
|
11
|
+
state_transition_catalog: [{transition_id: transition.example, aggregate_id: aggregate.example, from: draft, to: done, behavior_id: behavior.example}]
|
|
12
|
+
consistency_policy: {transaction_boundary: single, concurrency: optimistic, idempotency: guarded, cross_aggregate_strategy: none}
|
|
13
|
+
domain_event_catalog: []
|
|
14
|
+
gateway_catalog: [{gateway_id: gateway.example, name: Gateway, context_ref: context.example, layer: Domain, capabilities: [load]}]
|
|
15
|
+
persistence_mapping: [{aggregate_id: aggregate.example, storage_model: example, notes: mapping}]
|
|
16
|
+
test_seams: [{seam_id: test-seam.example, kind: domain, subject_ref: invariant.example, assertion: behavior}]
|
|
17
|
+
adr_candidates: []
|
|
18
|
+
upstream_impact: {spec_ref: spec@v1, strategic_ref: strategy@v1, api_ref: api@draft, data_ref: data@v1, upstream_current: true}
|
|
19
|
+
version: v1
|
|
20
|
+
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
21
|
+
evidence_refs: []
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
tactical_design_id: tactical-design.example-feature
|
|
3
|
+
tactical_version: v1
|
|
4
|
+
status: ready-for-human
|
|
5
|
+
context_ref: context.example
|
|
6
|
+
aggregate_catalog:
|
|
7
|
+
- aggregate_id: aggregate.example
|
|
8
|
+
name: ExampleAggregate
|
|
9
|
+
context_ref: context.example
|
|
10
|
+
root_entity: entity.example-root
|
|
11
|
+
invariant_refs: [invariant.example-required]
|
|
12
|
+
behavior_refs: [behavior.example-publish]
|
|
13
|
+
consistency_boundary: single-aggregate-transaction
|
|
14
|
+
api_exposure: internal-only
|
|
15
|
+
entity_catalog:
|
|
16
|
+
- entity_id: entity.example-root
|
|
17
|
+
name: ExampleRoot
|
|
18
|
+
aggregate_id: aggregate.example
|
|
19
|
+
identity: stable-id
|
|
20
|
+
lifecycle: draft-published
|
|
21
|
+
value_object_catalog:
|
|
22
|
+
- value_object_id: value-object.example-code
|
|
23
|
+
name: ExampleCode
|
|
24
|
+
aggregate_id: aggregate.example
|
|
25
|
+
immutable: true
|
|
26
|
+
behavior_catalog:
|
|
27
|
+
- behavior_id: behavior.example-publish
|
|
28
|
+
name: Publish
|
|
29
|
+
aggregate_id: aggregate.example
|
|
30
|
+
command: publish
|
|
31
|
+
preconditions: ["状态为 draft"]
|
|
32
|
+
invariant_refs: [invariant.example-required]
|
|
33
|
+
postconditions: ["状态变为 published"]
|
|
34
|
+
event_refs: [domain-event.example-published]
|
|
35
|
+
invariant_catalog:
|
|
36
|
+
- invariant_id: invariant.example-required
|
|
37
|
+
aggregate_id: aggregate.example
|
|
38
|
+
statement: "发布前必须满足业务前置条件"
|
|
39
|
+
state_transition_catalog:
|
|
40
|
+
- transition_id: transition.example-publish
|
|
41
|
+
aggregate_id: aggregate.example
|
|
42
|
+
from: draft
|
|
43
|
+
to: published
|
|
44
|
+
behavior_id: behavior.example-publish
|
|
45
|
+
consistency_policy:
|
|
46
|
+
transaction_boundary: single aggregate
|
|
47
|
+
concurrency: optimistic version check
|
|
48
|
+
idempotency: repeated publish is rejected by state guard
|
|
49
|
+
cross_aggregate_strategy: domain event with retry
|
|
50
|
+
domain_event_catalog:
|
|
51
|
+
- event_id: domain-event.example-published
|
|
52
|
+
name: ExamplePublished
|
|
53
|
+
aggregate_id: aggregate.example
|
|
54
|
+
consumers: [downstream-context]
|
|
55
|
+
delivery: outbox-at-least-once
|
|
56
|
+
gateway_catalog:
|
|
57
|
+
- gateway_id: gateway.example
|
|
58
|
+
name: ExampleGateway
|
|
59
|
+
context_ref: context.example
|
|
60
|
+
layer: Domain
|
|
61
|
+
capabilities: [save aggregate, load aggregate]
|
|
62
|
+
persistence_mapping:
|
|
63
|
+
- aggregate_id: aggregate.example
|
|
64
|
+
storage_model: example_aggregate_snapshot
|
|
65
|
+
notes: "持久化结构不泄漏到领域模型"
|
|
66
|
+
test_seams:
|
|
67
|
+
- seam_id: test-seam.example-invariant
|
|
68
|
+
kind: domain-behavior
|
|
69
|
+
subject_ref: invariant.example-required
|
|
70
|
+
assertion: "不满足前置条件时 publish 失败"
|
|
71
|
+
adr_candidates: []
|
|
72
|
+
upstream_impact:
|
|
73
|
+
spec_ref: docs/.scratch/example/spec.yaml@v1
|
|
74
|
+
strategic_ref: docs/.scratch/example/domain-strategy.yaml@v1
|
|
75
|
+
api_ref: docs/.scratch/example/openapi.yaml@draft
|
|
76
|
+
data_ref: docs/.scratch/example/data-architecture.md@v1
|
|
77
|
+
upstream_current: true
|
|
78
|
+
version: v1
|
|
79
|
+
digest: sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
80
|
+
evidence_refs: [docs/.scratch/example/tactical-review.yaml]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
|
|
8
|
+
const root = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const validator = join(root, "..", "scripts", "validate-tactical-design.mjs");
|
|
10
|
+
const fixture = (name) => join(root, "fixtures", name);
|
|
11
|
+
const run = (file) => spawnSync(process.execPath, [validator, file], { encoding: "utf8" });
|
|
12
|
+
const pass = run(fixture("valid-tactical-design.yaml"));
|
|
13
|
+
if (pass.status !== 0) throw new Error(`valid tactical design should pass: ${pass.stderr}`);
|
|
14
|
+
|
|
15
|
+
const blockedCases = [
|
|
16
|
+
["invalid-missing-invariant.yaml", "invariant_refs 必须是至少 1 项的数组"],
|
|
17
|
+
["invalid-api-leaks-aggregate.yaml", "api_exposure 必须为 internal-only"],
|
|
18
|
+
["invalid-stale-upstream-ref.yaml", "status 必须为 stale"],
|
|
19
|
+
["invalid-strategic-as-tactical.yaml", "不得直接把战略概念当作 Aggregate"],
|
|
20
|
+
["invalid-missing-consistency-policy.yaml", "consistency_policy.transaction_boundary 缺失"]
|
|
21
|
+
];
|
|
22
|
+
for (const [name, message] of blockedCases) {
|
|
23
|
+
const result = run(fixture(name));
|
|
24
|
+
if (result.status === 0 || !result.stderr.includes(message)) throw new Error(`${name} should be blocked: ${result.stderr}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const temporaryRoot = await mkdtemp(join(tmpdir(), "yss-tactical-design-pressure-"));
|
|
28
|
+
try {
|
|
29
|
+
const source = await readFile(fixture("valid-tactical-design.yaml"), "utf8");
|
|
30
|
+
const escalated = join(temporaryRoot, "missing-standalone-ref.yaml");
|
|
31
|
+
await writeFile(escalated, `${source}\ncomplexity:\n escalate_to_standalone: true\n`);
|
|
32
|
+
const result = run(escalated);
|
|
33
|
+
if (result.status === 0 || !result.stderr.includes("standalone_ref")) throw new Error("complexity escalation without standalone_ref should be blocked");
|
|
34
|
+
|
|
35
|
+
const wrongGateway = join(temporaryRoot, "wrong-gateway-layer.yaml");
|
|
36
|
+
await writeFile(wrongGateway, source.replace("layer: Domain", "layer: Infrastructure"));
|
|
37
|
+
const gatewayResult = run(wrongGateway);
|
|
38
|
+
if (gatewayResult.status === 0 || !gatewayResult.stderr.includes("layer 必须为 Domain")) throw new Error("Infrastructure gateway should be blocked");
|
|
39
|
+
|
|
40
|
+
const crossAggregateRoot = join(temporaryRoot, "cross-aggregate-root.yaml");
|
|
41
|
+
await writeFile(crossAggregateRoot, source.replace("aggregate_id: aggregate.example\n identity", "aggregate_id: aggregate.other\n identity"));
|
|
42
|
+
const crossAggregateResult = run(crossAggregateRoot);
|
|
43
|
+
if (crossAggregateResult.status === 0 || !crossAggregateResult.stderr.includes("root_entity 的 aggregate_id 必须与当前 Aggregate 一致")) throw new Error("cross-aggregate root should be blocked");
|
|
44
|
+
} finally {
|
|
45
|
+
await rm(temporaryRoot, { recursive: true, force: true });
|
|
46
|
+
}
|
|
47
|
+
process.stdout.write("DDD tactical design scenarios passed\n");
|
package/template/AGENTS.md
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
| 模板维护强度触发与最低等级 | `docs/process/maintenance-intensity.yaml` |
|
|
24
24
|
| 技能清单、来源、版本、哈希和投影目标 | `skills-lock.json` |
|
|
25
25
|
| 技能分层、别名、默认可发现性和运行时入口 | `docs/agents/yss-skill-registry.yaml`(当前 `status: shadow`,不作为 Router / 生命周期运行时入口) |
|
|
26
|
+
| 数字人角色、阶段协作组、运行时绑定与生命周期会签 | `docs/agents/digital-human-roles.yaml`;`docs/agents/digital-human-roles.md` 为操作说明 |
|
|
26
27
|
|
|
27
28
|
README、用户指南、根目录 `CLAUDE.md` 和其他说明文档只引用或解释上述事实,不重复定义同一规则。`CLAUDE.md` 是 Claude Code 入口指针,不是第二套 Agent 规则。
|
|
28
29
|
|
|
@@ -31,7 +32,8 @@ README、用户指南、根目录 `CLAUDE.md` 和其他说明文档只引用或
|
|
|
31
32
|
- 所有面向业务、产品、架构、实施、审查、发布和复盘的落地文档,正文统一使用简体中文。
|
|
32
33
|
- 英文专有名词、代码标识、API 路径、schema、类名、方法名、枚举值、错误码、命令、文件名和协议 metadata 保持原样。
|
|
33
34
|
- 新流程统一使用 Spec、Ticket、`to-spec`、`to-tickets`。过时术语和技能名只能出现在迁移指南或明确标注的旧项目上下文。
|
|
34
|
-
-
|
|
35
|
+
- `CONTEXT.md` 是 Spec 构建及其落地工具链的统一语言输入,也是所有会创建或修改稳定业务、产品、架构、实施、审查、发布和复盘资产的强制前置上下文。`yss-product-lifecycle`、其原生 work unit,以及 `grill-with-docs`、`to-spec`、`to-tickets`、`implement` 等显式兼容入口,在规划、起草、评审、拆 Ticket 或实现前都必须读取并持续消费它;工具无法读取或消费时必须暂停并返回 `blocked`,不得凭临场翻译、同义词或局部上下文继续。
|
|
36
|
+
- 稳定业务术语必须先在 `CONTEXT.md` 中登记 PascalCase `英文标识`,再进入 Spec、原型、契约、Ticket、代码或验证资产;代码类型 / 字段与契约 property 使用该词干按 `CONTEXT.md` 文首规则变形。改中文术语或英文标识都先回写 `CONTEXT.md`,并重新检查受影响资产;与词汇或 ADR 冲突时立即指出并先解决冲突。
|
|
35
37
|
|
|
36
38
|
## 4. `template-source` 模板维护路由
|
|
37
39
|
|
|
@@ -83,6 +85,7 @@ README、用户指南、根目录 `CLAUDE.md` 和其他说明文档只引用或
|
|
|
83
85
|
| merge / rebase 冲突 | `resolving-merge-conflicts` |
|
|
84
86
|
| 架构治理、难测模块或深模块设计 | `improve-codebase-architecture` / `codebase-design` |
|
|
85
87
|
| 跨线程、跨仓库、上下文过长或原型结论回流 | `handoff` 或等价交接记录 |
|
|
88
|
+
| 数字人角色、Agent 运行时协同或生命周期会签 | 先读 `docs/agents/digital-human-roles.yaml`。职称实例叠加在编排器上,不另起生命周期,不批准 Slice 合同、不设 `ready-for-agent`、不宣布可发布 |
|
|
86
89
|
| 本地知识库 init / refresh / rebuild,或要把研究结果落成持久 wiki | `llm-wiki`(落成持久 wiki 用 `ingest`;已映射 live 源变了用 `refresh`)。`template-source` 的 wiki-root 为 `.template-source/wiki`;`project-instance` 不附带源仓库编译树,需要时在仓库根 `wiki/` 执行 `init` |
|
|
87
90
|
|
|
88
91
|
业务行为默认按 `tdd` 使用已确认的公开 seam 逐切片实现。一次性生成、纯配置或流程文档不适用代码 TDD 时,必须记录例外理由和可执行验证方式。
|
|
@@ -95,15 +98,16 @@ README、用户指南、根目录 `CLAUDE.md` 和其他说明文档只引用或
|
|
|
95
98
|
|
|
96
99
|
## 10. 独立审查、验证和追踪
|
|
97
100
|
|
|
98
|
-
-
|
|
101
|
+
- 实现者不能承担命中的独立审查(含数字人)。模板维护按 L1 / L2 / L3 分别使用 self-check / 人工 checkpoint、聚焦独立审查、正式独立审查;模板发布、代码切片和高风险变更仍必须由其他 Agent 或独立审查者完成。
|
|
99
102
|
- 任何“完成 / 可合并 / 可发布”结论必须基于 fresh verification,不接受“之前跑过”或实现者自述。
|
|
100
|
-
-
|
|
103
|
+
- 会签门禁按 `docs/agents/digital-human-roles.yaml` 的 `gate_policy` 关闭,会签文件经 `scripts/verify-approval-record` 核验;`gate.release-ready`、对外商务承诺和运行时外部副作用仍须生物人。
|
|
104
|
+
- 在会签暂停、handoff、进入实现、合并或发布边界集中同步范围、验证证据、风险、会签点、Ticket 状态和下一步;阻塞、责任人变化或资产单独批准时立即同步。
|
|
101
105
|
- Git checkpoint 只包含本轮明确范围;获得用户授权后才提交或推送。
|
|
102
106
|
- 发布后或阶段性完成后做复盘判断;出现架构返工、验证返工、IMPORTANT / CRITICAL review finding 或人工确认延期时,落简体中文复盘并修订权威资产。
|
|
103
107
|
|
|
104
108
|
## 11. Subagent 协同
|
|
105
109
|
|
|
106
|
-
使用 subagent
|
|
110
|
+
使用 subagent 或其它 Agent 运行时前按 `docs/process/subagent-collaboration.md` 定义任务包和不重叠的写入范围,并同时写明数字人角色、`runtime_id`、从角色表复制的 `core_skills` / `forbidden_skills` 与 Explorer / Drafter / Worker / Reviewer / Verifier 执行态。实现者不担任独立审查者;仓库身份、Ticket 最终状态、Git checkpoint、Slice 合同批准和完成结论仍由主控数字人按编排器规则决定。会签恢复前校验 `scripts/verify-approval-record`。写隔离靠任务包;共享工作区不是默认沙箱。
|
|
107
111
|
|
|
108
112
|
## 12. 测试质量基线
|
|
109
113
|
|
package/template/CONTEXT.md
CHANGED
|
@@ -12,7 +12,19 @@
|
|
|
12
12
|
|
|
13
13
|
| 术语 | 含义 | 英文标识 | 避免 / 备注 |
|
|
14
14
|
|---|---|---|---|
|
|
15
|
-
| Agent | 执行特定工作流步骤的 AI 协作者。 | — |
|
|
15
|
+
| Agent | 执行特定工作流步骤的 AI 协作者。 | — | 不要与生物人审查者、数字人角色或 Ticket 状态混用。运行时实例(Cursor Agent、Claude Code、Grok Bot 等)是 Agent 的承载,不是角色本身。 |
|
|
16
|
+
| 运行时绑定 | 把数字人角色落到某个 Agent 平台的适配声明,权威清单在数字人角色注册表的 `runtimes`。 | — | 不要为每个平台复制一套职称职责。 |
|
|
17
|
+
| Grok Bot | Grok 平台上的持久数字队友实例;对应 `runtime.grok`。 | — | 不是数字人角色、技能或门禁。 |
|
|
18
|
+
| 数字人角色 | 叠加在生命周期编排器上的职称配置;一个运行时实例绑定一种。v1 清单以 `docs/agents/digital-human-roles.yaml` 为准。 | — | 不要称为 Ticket「标准角色」、职能 Agent 或某个平台的产品名。 |
|
|
19
|
+
| 主控数字人 | 运行 `yss-product-lifecycle` 的协调实例。 | — | 不是第八个业务职称;默认兼任项目经理。 |
|
|
20
|
+
| 角色配置 | 某数字人角色的关注阶段、技能包、可起草产物和禁止事项。 | — | 不是独立编排器,也不含平台群聊人数。 |
|
|
21
|
+
| 生命周期会签 | 指定数字人或生物人关闭 `gate.*` / 独立审查并写入 `evidence.approval-record`。 | — | 不是运行时副作用审批。会签人由 `docs/agents/digital-human-roles.yaml` 的 `gate_policy` 指定。起草者不得会签自己起草的资产。`paused-human-gate` 表示等待该会签人,不是必须生物人。 |
|
|
22
|
+
| 运行时副作用审批 | 对发消息、改生产、付款、删数据等工具动作的账号级确认。 | — | 点 Allow 不等于门禁已批准或可发布。避免只称「Grok 平台审批」。 |
|
|
23
|
+
| Ticket 状态 | Tracker 五态:`needs-triage`、`needs-info`、`ready-for-agent`、`ready-for-human`、`wontfix`。 | — | 不要称为数字人角色或「标准角色」。 |
|
|
24
|
+
| 阶段协作组 | 某阶段需要共同可见会签的逻辑成员集合。 | — | 不是某个产品的群聊;平台人数上限只写在对应 `runtimes`。 |
|
|
25
|
+
| 需求经理 | 主责 Discovery 语言、用户/MVP/非目标、Spec 正文与测试 seam 的数字人角色。 | — | 不拥有原型视觉定稿,不 Freeze API,不写实现。 |
|
|
26
|
+
| 产品经理 | 主责优先级、产品设计影响、原型确认建议和范围裁剪的数字人角色。 | — | 不写生产代码,不单独 Freeze API。 |
|
|
27
|
+
| 商务 | 主责机会调研商业约束、交付承诺和发布窗口商务非目标的数字人角色。 | — | 不参与 Spec 定稿、契约、代码或 Ticket 状态推进。 |
|
|
16
28
|
| Agent 入口规则 | Agent 启动任务时必须先遵守的全局路由、硬门禁和禁止事项。 | — | 不作为 YSS 后端、前端或其他专项编码规范的完整手册。 |
|
|
17
29
|
| 标准文档语言 | 面向业务、产品、架构、实施、审查、发布和复盘的持久化文档所使用的默认语言。 | — | 统一使用简体中文;英文专有名词、代码标识、API 路径、schema、文件名和协议 metadata 保持原样。 |
|
|
18
30
|
| Matt Engineering Skills | 来自 `mattpocock/skills` 的轻量工程流程技能集合。 | — | 用于澄清、Spec、Ticket、实现、TDD、诊断、审查和架构治理,不替代 YSS 专项规范。 |
|
|
@@ -25,7 +37,7 @@
|
|
|
25
37
|
| Ticket | 在追踪平台上承载功能生命周期或可实现工作单元的通用追踪对象。 | — | GitHub Issues / GitLab Issues 是具体平台对象名称;领域资产统一称为 Ticket。 |
|
|
26
38
|
| 功能父 Ticket | 汇总一个功能从 Spec 到契约冻结的阶段状态、资产链接、审查结论和阻塞项的 Ticket。 | — | 不作为 Agent 直接实现的垂直切片。 |
|
|
27
39
|
| 垂直切片 Ticket | 契约冻结后生成的可独立验证实现单元,记录范围、阻塞关系、验收标准和验证证据。 | — | 只有通过必要门禁并具备直接实现条件时才能标记 `ready-for-agent`。 |
|
|
28
|
-
| `ready-for-human` | 表示 Spec
|
|
40
|
+
| `ready-for-human` | 表示 Spec、设计、契约草案或其他资产仍需会签(指定数字人或生物人)。 | — | 此状态不表示可以直接进入实现;也不等于某个数字人角色。 |
|
|
29
41
|
| `ready-for-agent` | 表示垂直切片已通过必要门禁并具备直接实现条件的流程状态。 | — | 不得用于 Spec 初稿、原型、OpenAPI Draft 或其他未冻结资产。 |
|
|
30
42
|
| OpenAPI Draft | review-only 的 OpenAPI 3.1 契约草案。 | — | Freeze 前不得作为前后端稳定实现契约。 |
|
|
31
43
|
| OpenAPI Freeze | 已通过评审、可作为前后端实现和契约测试输入的 OpenAPI 3.1 契约。 | — | Freeze 后变更必须回到 API 影响分析和设计审查。 |
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# 数字人角色
|
|
2
|
+
|
|
3
|
+
结构化事实源是 `docs/agents/digital-human-roles.yaml`。角色、技能、协作组和会签级别与运行时无关。Claude Code、Cursor、Codex、Hermes、Grok Bot 等只通过 YAML `runtimes` 绑定。冲突时以 YAML 为准。
|
|
4
|
+
|
|
5
|
+
## 何时读本文
|
|
6
|
+
|
|
7
|
+
按职称派活、写会签、把数字人角色和 Ticket 状态 / 职能 Agent / 执行态弄混,或要在某个 Agent 平台上实例化这些角色时。
|
|
8
|
+
|
|
9
|
+
## 四条正交轴
|
|
10
|
+
|
|
11
|
+
| 轴 | 是什么 | 不是什么 |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| 数字人角色 | 职称配置(需求经理、前端工程师…) | Ticket 五态、某个平台的 Bot |
|
|
14
|
+
| 主控数字人 | 生命周期编排器的运行时实例 | 第八个业务职称 |
|
|
15
|
+
| 职能工作单元 | Discovery / Spec / Code / Review | 职称 |
|
|
16
|
+
| 执行态 | Explorer / Drafter / Worker / Reviewer / Verifier | 数字人角色 |
|
|
17
|
+
| 运行时绑定 | 如何在 Cursor / Claude / Grok 等落地 | 角色职责本身 |
|
|
18
|
+
|
|
19
|
+
一次数字人任务包同时写明 `task_id`、`work_unit_id`、`actor_id`、数字人角色、执行态、当前 `runtime_id`,以及从角色表复制的 `core_skills` / `forbidden_skills`。可用 `taskPackageDefaults(roleId)`(`scripts/lib/digital-human-roles.mjs`)读取,禁止手写第二套技能包。任务包 canonical Schema 为 `docs/process/schemas/digital-human-task-package.schema.json`,按 `contract.kind` 选择生命周期、切片实现或模板维护合同。
|
|
20
|
+
|
|
21
|
+
## 会签人
|
|
22
|
+
|
|
23
|
+
`gate_policy.digital_human_review` 与 `dual_digital_human` 是「门禁 × 起草者 × 会签人」规则,不是门禁名单。主控按 `countersigners` 派会签任务。
|
|
24
|
+
|
|
25
|
+
| 门禁 / 工作单元 | 起草 | 会签 |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| `gate.prototype-reviewed` | `role.product-manager` | `role.frontend-engineer` |
|
|
28
|
+
| `gate.openapi-draft-reviewed` | `role.backend-engineer` | `role.frontend-engineer` |
|
|
29
|
+
| `gate.engineering-baseline-accepted` | (实现者) | `role.test-engineer` |
|
|
30
|
+
| `gate.frontend-implementation-verified` | `role.frontend-engineer` | `role.test-engineer` |
|
|
31
|
+
| `work-unit.code-review` | 实现者 | `role.test-engineer`(必须不同实例) |
|
|
32
|
+
| `gate.spec-baseline-approved` | `role.requirements-manager` | `role.product-manager` |
|
|
33
|
+
| `gate.openapi-frozen` | `role.backend-engineer` | `role.product-manager`、`role.test-engineer` |
|
|
34
|
+
| `gate.user-confirmation` | — | `role.product-manager`;生物人可否决 |
|
|
35
|
+
| `gate.release-ready` | — | 生物人(`role.biological-human`) |
|
|
36
|
+
|
|
37
|
+
未列入表的门禁(含 `gate.design-reviewed`、`gate.architecture-reviewed`)走 `default_if_unlisted: biological-human`。
|
|
38
|
+
|
|
39
|
+
会签写入 `docs/.scratch/<feature>/gates/<gate-id>-approval.yaml`,形状见 `docs/templates/approval-record-template.yaml`。恢复前运行 `scripts/verify-approval-record`。错误会签只能得到 `blocked`,不能把门禁标成 `approved`。Checkpoint 里会签桶门禁为 `approved` 时必须有可读 `approval_ref`。
|
|
40
|
+
|
|
41
|
+
`paused-human-gate` 表示等待上述指定会签人,不是「必须是生物人」。
|
|
42
|
+
|
|
43
|
+
主控默认兼任项目经理,直到 `dual_hat_split_when`(`cross-repo-load` 或 `responsibility-conflict`)要求分体。
|
|
44
|
+
|
|
45
|
+
## 跨平台协同(默认)
|
|
46
|
+
|
|
47
|
+
1. 人默认只跟主控说话。
|
|
48
|
+
2. 主控按阶段 1:1 指定一个 owner,并给任务包(输入、写范围、禁止 skill、验收、验证命令)。
|
|
49
|
+
3. 需要可见会签时使用 YAML `stage_groups` 的**逻辑协作组**。这不是某个产品的群聊人数限制。
|
|
50
|
+
4. 权威结论写回 git。运行时记忆只记该数字人的稳定偏好。
|
|
51
|
+
5. 写隔离一律靠任务包。某运行时若共享磁盘或会话,适配器必须声明 `shared_workspace_is_not_security_boundary: true`,不得把实例当成沙箱。
|
|
52
|
+
6. `project-instance` 复制角色实例并绑定仓库路径。禁止按功能再拆实例。
|
|
53
|
+
7. 技能权威仍是 `.agents/skills`。已有投影根走 `runtime.skill-projection`,不要为职称再维护一份 skill。任务包的技能列表必须从角色表复制。
|
|
54
|
+
|
|
55
|
+
## 运行时绑定
|
|
56
|
+
|
|
57
|
+
| ID | 覆盖 | 落地方式 |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `runtime.generic` | 任何能加载 `core_skills` 并接受任务包的 Agent | 通用会话 / 人设 / system prompt |
|
|
60
|
+
| `runtime.skill-projection` | `yss-skill-registry.yaml` 的 `agent_runtime_roots`(claude、codex、cursor、hermes、pi、qoder、trae) | 投影技能 + subagent 任务包 |
|
|
61
|
+
| `runtime.grok` | Grok Bot | 持久 Bot、群聊或 1:1 交接;群超过 6 人改 1:1,不改逻辑协作组 |
|
|
62
|
+
|
|
63
|
+
新增平台:先加 `runtimes` 条目,再写适配说明。不要把平台限制写进 `roles`。
|
|
64
|
+
|
|
65
|
+
Grok 专用操作见 `docs/templates/grok-bot-profile-template.md`。通用实例化见 `docs/templates/digital-human-runtime-profile-template.md`。
|
|
66
|
+
|
|
67
|
+
## 两套批准
|
|
68
|
+
|
|
69
|
+
| 名称 | 关闭什么 | 谁点 |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| 运行时副作用审批 | 发消息、改生产、付款、删数据等工具动作 | 生物人(各平台自己的 Allow / 确认框) |
|
|
72
|
+
| 生命周期会签 | `gate.*` 与独立 code review | 见 YAML `gate_policy` |
|
|
73
|
+
|
|
74
|
+
会签写入 `docs/templates/approval-record-template.yaml`,带 `runtime_id`、`principal_ref` 与实例引用。起草者不得出现在会签人里。`gate.release-ready`、对外商务合同、运行时外部副作用,以及未列入会签表的 `gate.design-reviewed` / `gate.architecture-reviewed` 仍须生物人。
|
|
75
|
+
|
|
76
|
+
## 实例化
|
|
77
|
+
|
|
78
|
+
- 模板仓:`publish-singleton-profiles`。账户级只发布一套职称 profile,不按功能再拆。
|
|
79
|
+
- `project-instance`:`duplicate-and-bind-repo-path`。复制 YAML 的 `title` / `description` / `core_skills`,写入本仓库路径,选择 `runtime_id`。步骤见 `docs/templates/digital-human-runtime-profile-template.md`。外部 `create-yss-spec` 尚未接管此步骤。
|
|
80
|
+
|
|
81
|
+
## 任务包最低字段
|
|
82
|
+
|
|
83
|
+
`task_id`、`work_unit_id`、`actor_id`、数字人角色 ID、`runtime_id`、执行态、从角色表复制的 `core_skills` / `forbidden_skills`、`contract.kind/id/version`、输入资产、允许写路径、禁止事项、验收、验证命令、证据、下游消费者和汇合方式。
|