create-yss-spec 3.3.6 → 3.3.8
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 +12 -13
- package/package.json +1 -1
- package/src/template/instance-runtime.js +8 -2
- package/src/validation/snapshot.js +7 -0
- package/template/.agents/skills/.strategic-design-skills-manifest.json +6 -4
- package/template/.agents/skills/archify/SKILL.md +1 -1
- package/template/.agents/skills/implementation-repo-onboarding/SKILL.md +2 -2
- package/template/.agents/skills/yss-application/SKILL.md +1 -1
- package/template/.agents/skills/yss-application/references/profiles/existing-domain-driven-maven.md +5 -0
- package/template/.agents/skills/yss-application/references/profiles/existing-layered-mvc-maven.md +5 -0
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -2
- package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +4 -0
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +6 -1
- package/template/.agents/skills/yss-prototype-stage/SKILL.md +10 -1
- package/template/.agents/skills/yss-stage-decision/SKILL.md +13 -4
- package/template/.agents/skills/yss-stage-decision/references/domain-strategy-contract.md +4 -3
- package/template/.agents/skills/yss-stage-decision/references/domain-strategy-v2.schema.json +8 -0
- package/template/.agents/skills/yss-stage-decision/references/domain-strategy-v3.schema.json +8 -0
- package/template/.agents/skills/yss-stage-decision/references/domain-strategy.schema.json +75 -5
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-contract.md +4 -4
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-v2.schema.json +8 -0
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-v3.schema.json +8 -0
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package.schema.json +59 -9
- package/template/.agents/skills/yss-stage-decision/references/validation-rules.md +2 -2
- package/template/.agents/skills/yss-stage-decision/scripts/migrate-contract-v3.mjs +143 -0
- package/template/.agents/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +46 -4
- package/template/.agents/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +48 -4
- package/template/.agents/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +42 -13
- package/template/.agents/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +37 -5
- package/template/.agents/skills/yss-stage-decision/tests/run-scenarios.mjs +116 -23
- package/template/.agents/skills/yss-technical-design/SKILL.md +2 -0
- package/template/.agents/skills/yss-technical-design/references/engineering-design.schema.json +224 -0
- package/template/.agents/skills/yss-technical-design/references/technical-design-common.schema.json +6 -0
- package/template/.agents/skills/yss-technical-design/references/technical-design.schema.json +288 -10
- package/template/.agents/skills/yss-technical-design/scripts/engineering-design.mjs +30 -0
- package/template/.agents/skills/yss-technical-design/scripts/generate-schema.mjs +2 -1
- package/template/.agents/skills/yss-technical-design/scripts/validate-technical-design.mjs +20 -8
- package/template/.agents/skills/yss-technical-design/tests/engineering-scenarios.mjs +12 -0
- package/template/.agents/skills/yss-web-controller/SKILL.md +1 -1
- package/template/.agents/skills/yss-web-controller/references/profiles/existing-domain-driven-maven.md +5 -0
- package/template/.agents/skills/yss-web-controller/references/profiles/existing-layered-mvc-maven.md +5 -0
- package/template/.codex/skills/archify/SKILL.md +1 -1
- package/template/.codex/skills/implementation-repo-onboarding/SKILL.md +2 -2
- package/template/.codex/skills/yss-application/SKILL.md +1 -1
- package/template/.codex/skills/yss-application/references/profiles/existing-domain-driven-maven.md +5 -0
- package/template/.codex/skills/yss-application/references/profiles/existing-layered-mvc-maven.md +5 -0
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -2
- package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +4 -0
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +6 -1
- package/template/.codex/skills/yss-prototype-stage/SKILL.md +10 -1
- package/template/.codex/skills/yss-stage-decision/SKILL.md +13 -4
- package/template/.codex/skills/yss-stage-decision/references/domain-strategy-contract.md +4 -3
- package/template/.codex/skills/yss-stage-decision/references/domain-strategy-v2.schema.json +8 -0
- package/template/.codex/skills/yss-stage-decision/references/domain-strategy-v3.schema.json +8 -0
- package/template/.codex/skills/yss-stage-decision/references/domain-strategy.schema.json +75 -5
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-contract.md +4 -4
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-v2.schema.json +8 -0
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-v3.schema.json +8 -0
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package.schema.json +59 -9
- package/template/.codex/skills/yss-stage-decision/references/validation-rules.md +2 -2
- package/template/.codex/skills/yss-stage-decision/scripts/migrate-contract-v3.mjs +143 -0
- package/template/.codex/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +46 -4
- package/template/.codex/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +48 -4
- package/template/.codex/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +42 -13
- package/template/.codex/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +37 -5
- package/template/.codex/skills/yss-stage-decision/tests/run-scenarios.mjs +116 -23
- package/template/.codex/skills/yss-technical-design/SKILL.md +2 -0
- package/template/.codex/skills/yss-technical-design/references/engineering-design.schema.json +224 -0
- package/template/.codex/skills/yss-technical-design/references/technical-design-common.schema.json +6 -0
- package/template/.codex/skills/yss-technical-design/references/technical-design.schema.json +288 -10
- package/template/.codex/skills/yss-technical-design/scripts/engineering-design.mjs +30 -0
- package/template/.codex/skills/yss-technical-design/scripts/generate-schema.mjs +2 -1
- package/template/.codex/skills/yss-technical-design/scripts/validate-technical-design.mjs +20 -8
- package/template/.codex/skills/yss-technical-design/tests/engineering-scenarios.mjs +12 -0
- package/template/.codex/skills/yss-web-controller/SKILL.md +1 -1
- package/template/.codex/skills/yss-web-controller/references/profiles/existing-domain-driven-maven.md +5 -0
- package/template/.codex/skills/yss-web-controller/references/profiles/existing-layered-mvc-maven.md +5 -0
- package/template/.cursor/skills/archify/SKILL.md +1 -1
- package/template/.cursor/skills/implementation-repo-onboarding/SKILL.md +2 -2
- package/template/.cursor/skills/yss-application/SKILL.md +1 -1
- package/template/.cursor/skills/yss-application/references/profiles/existing-domain-driven-maven.md +5 -0
- package/template/.cursor/skills/yss-application/references/profiles/existing-layered-mvc-maven.md +5 -0
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -2
- package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +4 -0
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +6 -1
- package/template/.cursor/skills/yss-prototype-stage/SKILL.md +10 -1
- package/template/.cursor/skills/yss-stage-decision/SKILL.md +13 -4
- package/template/.cursor/skills/yss-stage-decision/references/domain-strategy-contract.md +4 -3
- package/template/.cursor/skills/yss-stage-decision/references/domain-strategy-v2.schema.json +8 -0
- package/template/.cursor/skills/yss-stage-decision/references/domain-strategy-v3.schema.json +8 -0
- package/template/.cursor/skills/yss-stage-decision/references/domain-strategy.schema.json +75 -5
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-contract.md +4 -4
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-v2.schema.json +8 -0
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-v3.schema.json +8 -0
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package.schema.json +59 -9
- package/template/.cursor/skills/yss-stage-decision/references/validation-rules.md +2 -2
- package/template/.cursor/skills/yss-stage-decision/scripts/migrate-contract-v3.mjs +143 -0
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +46 -4
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +48 -4
- package/template/.cursor/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +42 -13
- package/template/.cursor/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +37 -5
- package/template/.cursor/skills/yss-stage-decision/tests/run-scenarios.mjs +116 -23
- package/template/.cursor/skills/yss-technical-design/SKILL.md +2 -0
- package/template/.cursor/skills/yss-technical-design/references/engineering-design.schema.json +224 -0
- package/template/.cursor/skills/yss-technical-design/references/technical-design-common.schema.json +6 -0
- package/template/.cursor/skills/yss-technical-design/references/technical-design.schema.json +288 -10
- package/template/.cursor/skills/yss-technical-design/scripts/engineering-design.mjs +30 -0
- package/template/.cursor/skills/yss-technical-design/scripts/generate-schema.mjs +2 -1
- package/template/.cursor/skills/yss-technical-design/scripts/validate-technical-design.mjs +20 -8
- package/template/.cursor/skills/yss-technical-design/tests/engineering-scenarios.mjs +12 -0
- package/template/.cursor/skills/yss-web-controller/SKILL.md +1 -1
- package/template/.cursor/skills/yss-web-controller/references/profiles/existing-domain-driven-maven.md +5 -0
- package/template/.cursor/skills/yss-web-controller/references/profiles/existing-layered-mvc-maven.md +5 -0
- package/template/.pi/skills/archify/SKILL.md +1 -1
- package/template/.pi/skills/implementation-repo-onboarding/SKILL.md +2 -2
- package/template/.pi/skills/yss-application/SKILL.md +1 -1
- package/template/.pi/skills/yss-application/references/profiles/existing-domain-driven-maven.md +5 -0
- package/template/.pi/skills/yss-application/references/profiles/existing-layered-mvc-maven.md +5 -0
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -2
- package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +4 -0
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +6 -1
- package/template/.pi/skills/yss-prototype-stage/SKILL.md +10 -1
- package/template/.pi/skills/yss-stage-decision/SKILL.md +13 -4
- package/template/.pi/skills/yss-stage-decision/references/domain-strategy-contract.md +4 -3
- package/template/.pi/skills/yss-stage-decision/references/domain-strategy-v2.schema.json +8 -0
- package/template/.pi/skills/yss-stage-decision/references/domain-strategy-v3.schema.json +8 -0
- package/template/.pi/skills/yss-stage-decision/references/domain-strategy.schema.json +75 -5
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-contract.md +4 -4
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-v2.schema.json +8 -0
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-v3.schema.json +8 -0
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package.schema.json +59 -9
- package/template/.pi/skills/yss-stage-decision/references/validation-rules.md +2 -2
- package/template/.pi/skills/yss-stage-decision/scripts/migrate-contract-v3.mjs +143 -0
- package/template/.pi/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +46 -4
- package/template/.pi/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +48 -4
- package/template/.pi/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml +42 -13
- package/template/.pi/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml +37 -5
- package/template/.pi/skills/yss-stage-decision/tests/run-scenarios.mjs +116 -23
- package/template/.pi/skills/yss-technical-design/SKILL.md +2 -0
- package/template/.pi/skills/yss-technical-design/references/engineering-design.schema.json +224 -0
- package/template/.pi/skills/yss-technical-design/references/technical-design-common.schema.json +6 -0
- package/template/.pi/skills/yss-technical-design/references/technical-design.schema.json +288 -10
- package/template/.pi/skills/yss-technical-design/scripts/engineering-design.mjs +30 -0
- package/template/.pi/skills/yss-technical-design/scripts/generate-schema.mjs +2 -1
- package/template/.pi/skills/yss-technical-design/scripts/validate-technical-design.mjs +20 -8
- package/template/.pi/skills/yss-technical-design/tests/engineering-scenarios.mjs +12 -0
- package/template/.pi/skills/yss-web-controller/SKILL.md +1 -1
- package/template/.pi/skills/yss-web-controller/references/profiles/existing-domain-driven-maven.md +5 -0
- package/template/.pi/skills/yss-web-controller/references/profiles/existing-layered-mvc-maven.md +5 -0
- package/template/README.md +4 -6
- package/template/docs/agents/backend-architecture-profiles.md +4 -0
- package/template/docs/agents/yss-skill-registry.yaml +13 -0
- package/template/docs/design/templates/prototype-confirmation-template.md +2 -2
- package/template/docs/design/templates/prototype-review-checklist.md +2 -2
- package/template/docs/plan/templates/market-analysis-template.md +3 -3
- package/template/docs/plan/templates/user-pain-points-template.md +3 -3
- package/template/docs/process/delivery-preflight.md +72 -0
- package/template/docs/process/document-writing.md +5 -1
- package/template/docs/process/existing-backend-architecture.md +31 -0
- package/template/docs/process/existing-ui-baseline.md +40 -0
- package/template/docs/process/frontend-backend-delivery.md +21 -5
- package/template/docs/process/implementation-repo-integration.md +6 -0
- package/template/docs/process/schemas/backend-architecture-identity.schema.json +111 -14
- package/template/docs/process/schemas/backend-delivery.schema.json +4 -0
- package/template/docs/process/schemas/delivery-preflight-input.schema.json +158 -0
- package/template/docs/process/schemas/delivery-preflight-result.schema.json +159 -0
- package/template/docs/process/schemas/digital-human-task-package.schema.json +1 -1
- package/template/docs/process/schemas/existing-ui-baseline.schema.json +365 -0
- package/template/docs/process/schemas/frontend-delivery-acceptance-v1.schema.json +200 -0
- package/template/docs/process/schemas/frontend-delivery-acceptance-v3.schema.json +308 -0
- package/template/docs/process/schemas/frontend-delivery-acceptance.schema.json +37 -3
- package/template/docs/process/schemas/frontend-strategic-preflight-v2.schema.json +114 -0
- package/template/docs/process/schemas/frontend-strategic-preflight.schema.json +32 -0
- package/template/docs/process/schemas/lifecycle-checkpoint.schema.json +2 -1
- package/template/docs/process/schemas/strategic-consumer-feedback.schema.json +40 -0
- package/template/docs/process/schemas/strategic-design-handoff-v3.schema.json +743 -0
- package/template/docs/process/schemas/strategic-design-handoff-v4.schema.json +712 -0
- package/template/docs/process/schemas/strategic-design-handoff-v5.schema.json +932 -0
- package/template/docs/process/schemas/strategic-feedback-adjudication.schema.json +42 -0
- package/template/docs/process/schemas/strategic-handoff-domain-strategy-v3.schema.json +216 -0
- package/template/docs/process/schemas/strategic-handoff-export-v2.schema.json +378 -0
- package/template/docs/process/schemas/strategic-handoff-import-receipt.schema.json +39 -0
- package/template/docs/process/schemas/strategic-handoff-stage-decision-package-v3.schema.json +148 -0
- package/template/docs/process/strategic-handoff-package.md +51 -10
- package/template/docs/process/templates/lifecycle-checkpoint-template.yaml +1 -0
- package/template/docs/process/templates/stage-checkpoint-template.md +1 -0
- package/template/docs/user-guide//346/212/200/346/234/257/350/256/276/350/256/241/347/224/250/346/210/267/346/214/207/345/215/227.md +43 -0
- package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +83 -67
- package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214/347/264/242/345/274/225.md +9 -10
- 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 +12 -9
- package/template/scripts/backend-delivery +20 -4
- package/template/scripts/lib/approval-record.mjs +2 -1
- package/template/scripts/lib/approved-execution-context.mjs +106 -0
- package/template/scripts/lib/backend-architecture.mjs +12 -0
- package/template/scripts/lib/backend-delivery.mjs +21 -5
- package/template/scripts/lib/delivery-preflight.mjs +238 -0
- package/template/scripts/lib/existing-backend-architecture.mjs +139 -0
- package/template/scripts/lib/existing-ui-baseline.mjs +84 -0
- package/template/scripts/lib/frontend-delivery-boundary.mjs +20 -4
- package/template/scripts/lib/frontend-delivery.mjs +76 -4
- package/template/scripts/lib/implementation-contract-compiler.mjs +19 -5
- package/template/scripts/lib/json-schema.mjs +19 -4
- package/template/scripts/lib/profile-skill-sync.mjs +26 -0
- package/template/scripts/lib/strategic-feedback.mjs +33 -0
- package/template/scripts/lib/strategic-handoff-consumption.mjs +11 -5
- package/template/scripts/lib/strategic-handoff-design-targets.mjs +2 -3
- package/template/scripts/lib/strategic-handoff-io.mjs +11 -0
- package/template/scripts/lib/strategic-handoff.mjs +143 -34
- package/template/scripts/lib/task-package.mjs +11 -3
- package/template/scripts/lib/technical-design-boundary.mjs +9 -1
- package/template/scripts/lib/ui-baseline.mjs +26 -0
- package/template/scripts/lib/user-decision-reuse.mjs +38 -0
- package/template/scripts/lib/user-decision.mjs +4 -1
- package/template/scripts/preflight-delivery +14 -0
- package/template/scripts/strategic-feedback +10 -0
- package/template/scripts/strategic-handoff +19 -4
- package/template/scripts/sync-profile-skills +4 -5
- package/template/scripts/verify-frontend-strategic-preflight +12 -0
- package/template/skills-lock.json +18 -18
- package/template.manifest.json +1 -0
- package/template.snapshot.json +6 -5
- 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 +0 -35
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { buildDecisionFixture } from "../../../../scripts/fixtures/user-decision/build-fixture.mjs";
|
|
3
2
|
import { createHash } from "node:crypto";
|
|
4
3
|
import { spawnSync } from "node:child_process";
|
|
5
4
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
@@ -14,6 +13,7 @@ const validator = join(testsRoot, "..", "scripts", "validate-domain-strategy.mjs
|
|
|
14
13
|
const packageValidator = join(testsRoot, "..", "scripts", "validate-stage-decision-package.mjs");
|
|
15
14
|
const contextValidator = join(projectRoot, "scripts", "verify-context-contract");
|
|
16
15
|
const migrationTool = join(testsRoot, "..", "scripts", "migrate-context-references.mjs");
|
|
16
|
+
const v3MigrationTool = join(testsRoot, "..", "scripts", "migrate-contract-v3.mjs");
|
|
17
17
|
const validTemplate = join(testsRoot, "fixtures", "valid-supplier-domain.yaml");
|
|
18
18
|
const validPackageTemplate = join(testsRoot, "fixtures", "valid-stage-decision-package.yaml");
|
|
19
19
|
|
|
@@ -29,6 +29,58 @@ function digestYaml(source) {
|
|
|
29
29
|
return `sha256:${createHash("sha256").update(JSON.stringify(canonical(document.toJS({ maxAliasCount: 0 })))).digest("hex")}`;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function parseYaml(source) {
|
|
33
|
+
const document = parseDocument(source, { maxAliasCount: 0, uniqueKeys: true });
|
|
34
|
+
if (document.errors.length) throw new Error(document.errors[0].message);
|
|
35
|
+
return document.toJS({ maxAliasCount: 0 });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function toV2Domain(source) {
|
|
39
|
+
const value = structuredClone(parseYaml(source));
|
|
40
|
+
value.schema_version = 2;
|
|
41
|
+
value.domain_version = "v2";
|
|
42
|
+
delete value.traceability_version;
|
|
43
|
+
delete value.rule_catalog;
|
|
44
|
+
for (const scenario of value.scenarios) {
|
|
45
|
+
delete scenario.rule_refs;
|
|
46
|
+
delete scenario.critical;
|
|
47
|
+
delete scenario.success_results;
|
|
48
|
+
delete scenario.evidence_refs;
|
|
49
|
+
}
|
|
50
|
+
for (const invariant of value.invariants) {
|
|
51
|
+
delete invariant.rule_ref;
|
|
52
|
+
delete invariant.evidence_refs;
|
|
53
|
+
}
|
|
54
|
+
value.downstream_mapping = [{
|
|
55
|
+
domain_change: "admission-decision-validity",
|
|
56
|
+
impacts: ["spec", "openapi", "procurement-acceptance-tests"],
|
|
57
|
+
propagation: "stale",
|
|
58
|
+
reapproval_condition: "ComplianceReview 决定和有效期重新批准"
|
|
59
|
+
}];
|
|
60
|
+
value.approval.current_version = "v2";
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function toV2Stage(source, domainDigest) {
|
|
65
|
+
const value = structuredClone(parseYaml(source));
|
|
66
|
+
value.schema_version = 2;
|
|
67
|
+
value.package_version = "v2";
|
|
68
|
+
for (const field of ["success_criteria", "test_seams", "confirmed_decisions", "assumptions", "constraints"]) {
|
|
69
|
+
value[field] = value[field].map((item) => item.statement);
|
|
70
|
+
}
|
|
71
|
+
value.domain_strategy_ref.domain_version = "v2";
|
|
72
|
+
value.domain_strategy_ref.digest = domainDigest;
|
|
73
|
+
value.domain_strategy_ref.persisted_ref = "domain-strategy-v2.yaml";
|
|
74
|
+
value.downstream_mapping = [{
|
|
75
|
+
domain_change: "admission-decision-validity",
|
|
76
|
+
consumer: "spec-synthesis",
|
|
77
|
+
propagation: "direct",
|
|
78
|
+
reapproval_condition: "领域策略版本或有效性规则变化"
|
|
79
|
+
}];
|
|
80
|
+
value.approval.current_version = "v2";
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
|
|
32
84
|
function run(command, file, contextRoot) {
|
|
33
85
|
return spawnSync(process.execPath, [command, file, "--root", contextRoot], { cwd: projectRoot, encoding: "utf8" });
|
|
34
86
|
}
|
|
@@ -56,34 +108,59 @@ context_schema_version: 1
|
|
|
56
108
|
| 准入决定 | 合规审查形成的准入结论。 | AdmissionDecision | ComplianceReview | 避免:\`审批结果\` |
|
|
57
109
|
`;
|
|
58
110
|
|
|
59
|
-
const temporaryRoot = await mkdtemp(join(tmpdir(), "yss-stage-decision-
|
|
111
|
+
const temporaryRoot = await mkdtemp(join(tmpdir(), "yss-stage-decision-v3-"));
|
|
60
112
|
try {
|
|
61
113
|
await writeFile(join(temporaryRoot, "CONTEXT.md"), contextSource);
|
|
62
114
|
const contextResult = spawnSync(process.execPath, [contextValidator, "--root", temporaryRoot, "--allowed-context", "SupplierManagement", "--allowed-context", "ComplianceReview", "--allowed-context", "ProcurementExecution", "--term-ref", "Global/Supplier", "--term-ref", "ComplianceReview/AdmissionDecision", "--json"], { cwd: projectRoot, encoding: "utf8" });
|
|
63
115
|
if (contextResult.status !== 0) throw new Error(`context fixture should pass: ${contextResult.stderr}`);
|
|
64
116
|
const context = JSON.parse(contextResult.stdout);
|
|
65
117
|
|
|
66
|
-
const domainApprovalRef = join(temporaryRoot, "domain-approval.json");
|
|
67
118
|
const domainSource = (await readFile(validTemplate, "utf8"))
|
|
68
|
-
.replace(".agents/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml", domainApprovalRef)
|
|
69
119
|
.replace("<document-digest>", context.document_digest)
|
|
70
120
|
.replace("<referenced-terms-digest>", context.referenced_terms_digest);
|
|
71
121
|
const domainFile = join(temporaryRoot, "domain-strategy.yaml");
|
|
72
122
|
await writeFile(domainFile, domainSource);
|
|
73
|
-
const domainDecision = buildDecisionFixture(join(temporaryRoot, "domain-decision"), { boundary: "check.domain-strategy-approved", subjectRef: domainFile });
|
|
74
|
-
const domainApproval = parseDocument(await readFile(join(testsRoot, "fixtures/domain-strategy-approval.yaml"), "utf8")).toJS();
|
|
75
|
-
await writeFile(domainApprovalRef, JSON.stringify({ ...domainApproval, subject_ref: domainFile, approval_scope: domainDecision.requirement.scope, user_decision_ref: domainDecision.ref }));
|
|
76
123
|
const pass = run(validator, domainFile, temporaryRoot);
|
|
77
|
-
if (pass.status !== 0) throw new Error(`valid
|
|
124
|
+
if (pass.status !== 0) throw new Error(`valid v3 fixture should pass: ${pass.stderr}`);
|
|
125
|
+
|
|
126
|
+
const v2Domain = toV2Domain(domainSource);
|
|
127
|
+
const v2DomainSource = JSON.stringify(v2Domain, null, 2);
|
|
128
|
+
const v2DomainFile = join(temporaryRoot, "domain-strategy-v2.yaml");
|
|
129
|
+
await writeFile(v2DomainFile, v2DomainSource);
|
|
130
|
+
const v2Pass = run(validator, v2DomainFile, temporaryRoot);
|
|
131
|
+
if (v2Pass.status !== 0) throw new Error(`read-only v2 fixture should pass: ${v2Pass.stderr}`);
|
|
132
|
+
|
|
133
|
+
const migratedDomainV3 = spawnSync(process.execPath, [v3MigrationTool, v2DomainFile, "--kind", "domain-strategy", "--root", temporaryRoot], { cwd: projectRoot, encoding: "utf8" });
|
|
134
|
+
if (migratedDomainV3.status !== 0) throw new Error(`v2 domain strategy should migrate: ${migratedDomainV3.stderr}`);
|
|
135
|
+
const migratedDomainV3Value = JSON.parse(migratedDomainV3.stdout);
|
|
136
|
+
if (migratedDomainV3Value.schema_version !== 3 || migratedDomainV3Value.status !== "draft" || migratedDomainV3Value.approval.approval_ref !== "migration-required") throw new Error("domain v2 -> v3 migration must reset approval and status");
|
|
137
|
+
|
|
138
|
+
const duplicateRule = join(temporaryRoot, "duplicate-rule.yaml");
|
|
139
|
+
const duplicateRuleValue = parseYaml(domainSource);
|
|
140
|
+
duplicateRuleValue.rule_catalog.push(structuredClone(duplicateRuleValue.rule_catalog[0]));
|
|
141
|
+
await writeFile(duplicateRule, JSON.stringify(duplicateRuleValue, null, 2));
|
|
142
|
+
expectBlocked(run(validator, duplicateRule, temporaryRoot), /rule_id.*重复|重复.*rule_id/, "duplicate v3 rule id");
|
|
143
|
+
|
|
144
|
+
const danglingRule = join(temporaryRoot, "dangling-rule.yaml");
|
|
145
|
+
const danglingRuleValue = parseYaml(domainSource);
|
|
146
|
+
danglingRuleValue.scenarios[0].rule_refs = ["rule.missing"];
|
|
147
|
+
await writeFile(danglingRule, JSON.stringify(danglingRuleValue, null, 2));
|
|
148
|
+
expectBlocked(run(validator, danglingRule, temporaryRoot), /rule_refs.*未声明|悬空/, "dangling v3 rule ref");
|
|
149
|
+
|
|
150
|
+
const missingEvidence = join(temporaryRoot, "missing-rule-evidence.yaml");
|
|
151
|
+
const missingEvidenceValue = parseYaml(domainSource);
|
|
152
|
+
missingEvidenceValue.rule_catalog[0].evidence_refs = [];
|
|
153
|
+
await writeFile(missingEvidence, JSON.stringify(missingEvidenceValue, null, 2));
|
|
154
|
+
expectBlocked(run(validator, missingEvidence, temporaryRoot), /evidence_refs/, "missing v3 evidence");
|
|
78
155
|
|
|
79
156
|
const legacyFile = join(temporaryRoot, "legacy-domain.yaml");
|
|
80
|
-
await writeFile(legacyFile,
|
|
157
|
+
await writeFile(legacyFile, JSON.stringify({ ...v2Domain, schema_version: 1 }, null, 2));
|
|
81
158
|
expectBlocked(run(validator, legacyFile, temporaryRoot), /migration-required/, "legacy domain contract");
|
|
82
159
|
|
|
83
160
|
const migratableLegacy = join(temporaryRoot, "migratable-legacy-domain.yaml");
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
161
|
+
const migratableLegacyValue = { ...structuredClone(v2Domain), schema_version: 1, terminology_refs: ["CONTEXT.md#Supplier", "contexts/ComplianceReview/CONTEXT.md#AdmissionDecision"] };
|
|
162
|
+
delete migratableLegacyValue.context_snapshot;
|
|
163
|
+
const migratableLegacySource = JSON.stringify(migratableLegacyValue, null, 2);
|
|
87
164
|
await writeFile(migratableLegacy, migratableLegacySource);
|
|
88
165
|
const migrated = spawnSync(process.execPath, [migrationTool, migratableLegacy, "--root", temporaryRoot], { cwd: projectRoot, encoding: "utf8" });
|
|
89
166
|
if (migrated.status !== 0) throw new Error(`migratable v1 contract should migrate: ${migrated.stderr}`);
|
|
@@ -91,7 +168,7 @@ try {
|
|
|
91
168
|
if (migratedValue.schema_version !== 2 || migratedValue.terminology_refs !== undefined || migratedValue.context_snapshot.context_ref !== "CONTEXT.md" || migratedValue.context_snapshot.term_refs.join(",") !== "ComplianceReview/AdmissionDecision,Global/Supplier") throw new Error("migrated context snapshot is incomplete");
|
|
92
169
|
|
|
93
170
|
const ambiguousLegacy = join(temporaryRoot, "ambiguous-legacy-domain.yaml");
|
|
94
|
-
await writeFile(ambiguousLegacy,
|
|
171
|
+
await writeFile(ambiguousLegacy, JSON.stringify({ ...migratableLegacyValue, terminology_refs: ["contexts/ComplianceReview/CONTEXT.md"] }, null, 2));
|
|
95
172
|
const ambiguousMigration = spawnSync(process.execPath, [migrationTool, ambiguousLegacy, "--root", temporaryRoot], { cwd: projectRoot, encoding: "utf8" });
|
|
96
173
|
expectBlocked(ambiguousMigration, /migration-required.*无法唯一定位|无法唯一定位.*migration-required/, "ambiguous legacy reference");
|
|
97
174
|
|
|
@@ -115,32 +192,48 @@ try {
|
|
|
115
192
|
await writeFile(unknownContext, domainSource.replace("to_context: ComplianceReview", "to_context: UnknownContext"));
|
|
116
193
|
expectBlocked(run(validator, unknownContext, temporaryRoot), /未引用已声明上下文|未在领域战略中登记/, "unknown context");
|
|
117
194
|
|
|
118
|
-
const packageApprovalRef = join(temporaryRoot, "package-approval.json");
|
|
119
195
|
const packageSource = (await readFile(validPackageTemplate, "utf8"))
|
|
120
|
-
.replace(".agents/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml", packageApprovalRef)
|
|
121
196
|
.replace("<document-digest>", context.document_digest)
|
|
122
197
|
.replace("<referenced-terms-digest>", context.referenced_terms_digest)
|
|
123
198
|
.replace("<domain-strategy-digest>", digestYaml(domainSource));
|
|
124
199
|
const packageFile = join(temporaryRoot, "stage-decision.yaml");
|
|
125
200
|
await writeFile(packageFile, packageSource);
|
|
126
|
-
const packageDecision = buildDecisionFixture(join(temporaryRoot, "package-decision"), { boundary: "check.stage-decision-package-approved", subjectRef: packageFile });
|
|
127
|
-
const packageApproval = parseDocument(await readFile(join(testsRoot, "fixtures/stage-decision-approval.yaml"), "utf8")).toJS();
|
|
128
|
-
await writeFile(packageApprovalRef, JSON.stringify({ ...packageApproval, subject_ref: packageFile, approval_scope: packageDecision.requirement.scope, user_decision_ref: packageDecision.ref }));
|
|
129
201
|
const packagePass = run(packageValidator, packageFile, temporaryRoot);
|
|
130
|
-
if (packagePass.status !== 0) throw new Error(`valid
|
|
202
|
+
if (packagePass.status !== 0) throw new Error(`valid v3 stage decision package should pass: ${packagePass.stderr}`);
|
|
203
|
+
|
|
204
|
+
const v2Stage = toV2Stage(packageSource, digestYaml(v2DomainSource));
|
|
205
|
+
const v2StageFile = join(temporaryRoot, "stage-decision-v2.yaml");
|
|
206
|
+
await writeFile(v2StageFile, JSON.stringify(v2Stage, null, 2));
|
|
207
|
+
const v2StagePass = run(packageValidator, v2StageFile, temporaryRoot);
|
|
208
|
+
if (v2StagePass.status !== 0) throw new Error(`read-only v2 stage decision package should pass: ${v2StagePass.stderr}`);
|
|
209
|
+
|
|
210
|
+
const migratedV3 = spawnSync(process.execPath, [v3MigrationTool, v2StageFile, "--kind", "stage-decision", "--root", temporaryRoot], { cwd: projectRoot, encoding: "utf8" });
|
|
211
|
+
if (migratedV3.status !== 0) throw new Error(`v2 stage decision should migrate: ${migratedV3.stderr}`);
|
|
212
|
+
const migratedV3Value = JSON.parse(migratedV3.stdout);
|
|
213
|
+
if (migratedV3Value.schema_version !== 3 || migratedV3Value.status !== "draft" || migratedV3Value.approval.approval_ref !== "migration-required") throw new Error("v2 -> v3 migration must reset approval and status");
|
|
214
|
+
|
|
215
|
+
const wrongSourceRef = join(temporaryRoot, "stage-decision-wrong-source-ref.yaml");
|
|
216
|
+
const wrongSourceRefValue = parseYaml(packageSource);
|
|
217
|
+
wrongSourceRefValue.success_criteria[0].source_refs = ["rule.missing"];
|
|
218
|
+
await writeFile(wrongSourceRef, JSON.stringify(wrongSourceRefValue, null, 2));
|
|
219
|
+
expectBlocked(run(packageValidator, wrongSourceRef, temporaryRoot), /source_refs.*未在领域战略中声明|悬空/, "stage decision dangling source ref");
|
|
131
220
|
|
|
132
221
|
const packageLegacy = join(temporaryRoot, "legacy-stage-decision.yaml");
|
|
133
|
-
await writeFile(packageLegacy,
|
|
222
|
+
await writeFile(packageLegacy, JSON.stringify({ ...v2Stage, schema_version: 1 }, null, 2));
|
|
134
223
|
expectBlocked(run(packageValidator, packageLegacy, temporaryRoot), /migration-required/, "legacy stage decision contract");
|
|
135
224
|
|
|
136
225
|
const packageBlocker = join(temporaryRoot, "stage-decision-blocker.yaml");
|
|
137
|
-
|
|
226
|
+
const blockerValue = parseYaml(packageSource);
|
|
227
|
+
blockerValue.unresolved_items[0].type = "blocker";
|
|
228
|
+
await writeFile(packageBlocker, JSON.stringify(blockerValue, null, 2));
|
|
138
229
|
expectBlocked(run(packageValidator, packageBlocker, temporaryRoot), /blocker/, "blocker package");
|
|
139
230
|
|
|
140
231
|
const packageWrongArray = join(temporaryRoot, "stage-decision-wrong-array.yaml");
|
|
141
|
-
|
|
232
|
+
const wrongArrayValue = parseYaml(packageSource);
|
|
233
|
+
wrongArrayValue.target_users = [42];
|
|
234
|
+
await writeFile(packageWrongArray, JSON.stringify(wrongArrayValue, null, 2));
|
|
142
235
|
expectBlocked(run(packageValidator, packageWrongArray, temporaryRoot), /target_users\[0\]/, "package non-string array item");
|
|
143
236
|
} finally {
|
|
144
237
|
await rm(temporaryRoot, { recursive: true, force: true });
|
|
145
238
|
}
|
|
146
|
-
process.stdout.write("业务边界与规则设计 v2 场景验证通过\n");
|
|
239
|
+
process.stdout.write("业务边界与规则设计 v2/v3 场景验证通过\n");
|
|
@@ -24,6 +24,8 @@ description: 在 YSS 技术分析中统一承接需求与战略输入,按已
|
|
|
24
24
|
|
|
25
25
|
已有 Strategic Design Handoff 时,两种分支都必须先完成导入和目标词汇对账,再逐条承接规则与关键场景。没有战略交接包的项目直接消费批准需求,不能为 MVC 补造战略 DDD。
|
|
26
26
|
|
|
27
|
+
既有身份 v2 的纯工程变更可显式使用 `design_scope: engineering-only`;按 `references/engineering-design.schema.json` 绑定真实构建单元、写路径、只读依赖、失败处理与测试 seam。不得更改登记业务边界、领域模型、业务规则/状态、持久化、数据库 schema 或 UI;命中这些影响回原架构设计。缺省仍保留原 DDD/MVC 规则,不自动降级。工程分支仍需当前 Spec/API/工程依据、逐条承接、独立技术审查及正式 Slice 批准。
|
|
28
|
+
|
|
27
29
|
## 合同与验证
|
|
28
30
|
|
|
29
31
|
新产物使用 schema v2 Technical Design Contract:共同头记录架构来源、输入版本与摘要、规则/场景承接、评审证据和状态,`design` 保存架构专属内容。合同格式与兼容规则见 `references/technical-design-contract.md`,Schema 见 `references/technical-design.schema.json`。
|
package/template/.cursor/skills/yss-technical-design/references/engineering-design.schema.json
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "object",
|
|
3
|
+
"properties": {
|
|
4
|
+
"scope_reason": {
|
|
5
|
+
"type": "string",
|
|
6
|
+
"minLength": 1
|
|
7
|
+
},
|
|
8
|
+
"impact_assessment": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"domain_model": {
|
|
12
|
+
"const": "none"
|
|
13
|
+
},
|
|
14
|
+
"business_state": {
|
|
15
|
+
"const": "none"
|
|
16
|
+
},
|
|
17
|
+
"business_rules": {
|
|
18
|
+
"const": "none"
|
|
19
|
+
},
|
|
20
|
+
"business_persistence": {
|
|
21
|
+
"const": "none"
|
|
22
|
+
},
|
|
23
|
+
"schema_migration": {
|
|
24
|
+
"const": "none"
|
|
25
|
+
},
|
|
26
|
+
"ui_change": {
|
|
27
|
+
"const": "none"
|
|
28
|
+
},
|
|
29
|
+
"architecture_boundary_change": {
|
|
30
|
+
"const": "none"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"required": [
|
|
34
|
+
"domain_model",
|
|
35
|
+
"business_state",
|
|
36
|
+
"business_rules",
|
|
37
|
+
"business_persistence",
|
|
38
|
+
"schema_migration",
|
|
39
|
+
"ui_change",
|
|
40
|
+
"architecture_boundary_change"
|
|
41
|
+
],
|
|
42
|
+
"additionalProperties": false
|
|
43
|
+
},
|
|
44
|
+
"component_catalog": {
|
|
45
|
+
"type": "array",
|
|
46
|
+
"minItems": 1,
|
|
47
|
+
"items": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"properties": {
|
|
50
|
+
"component_id": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"minLength": 1
|
|
53
|
+
},
|
|
54
|
+
"responsibility": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"minLength": 1
|
|
57
|
+
},
|
|
58
|
+
"build_unit_ref": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"minLength": 1
|
|
61
|
+
},
|
|
62
|
+
"write_paths": {
|
|
63
|
+
"type": "array",
|
|
64
|
+
"minItems": 1,
|
|
65
|
+
"items": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"minLength": 1
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"depends_on": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"minItems": 0,
|
|
73
|
+
"items": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"minLength": 1
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"required": [
|
|
80
|
+
"component_id",
|
|
81
|
+
"responsibility",
|
|
82
|
+
"build_unit_ref",
|
|
83
|
+
"write_paths",
|
|
84
|
+
"depends_on"
|
|
85
|
+
],
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"allowed_write_paths": {
|
|
90
|
+
"type": "array",
|
|
91
|
+
"minItems": 1,
|
|
92
|
+
"items": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"minLength": 1
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"read_dependencies": {
|
|
98
|
+
"type": "array",
|
|
99
|
+
"minItems": 1,
|
|
100
|
+
"items": {
|
|
101
|
+
"type": "object",
|
|
102
|
+
"properties": {
|
|
103
|
+
"ref": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"minLength": 1
|
|
106
|
+
},
|
|
107
|
+
"digest": {
|
|
108
|
+
"type": "string",
|
|
109
|
+
"pattern": "^sha256:[a-f0-9]{64}$"
|
|
110
|
+
},
|
|
111
|
+
"purpose": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"minLength": 1
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"required": [
|
|
117
|
+
"ref",
|
|
118
|
+
"digest",
|
|
119
|
+
"purpose"
|
|
120
|
+
],
|
|
121
|
+
"additionalProperties": false
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
"flow": {
|
|
125
|
+
"type": "array",
|
|
126
|
+
"minItems": 1,
|
|
127
|
+
"items": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"minLength": 1
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"failure_handling": {
|
|
133
|
+
"type": "string",
|
|
134
|
+
"minLength": 1
|
|
135
|
+
},
|
|
136
|
+
"consistency_policy": {
|
|
137
|
+
"type": "object",
|
|
138
|
+
"properties": {
|
|
139
|
+
"read_only": {
|
|
140
|
+
"const": "read-only"
|
|
141
|
+
},
|
|
142
|
+
"transaction_boundary": {
|
|
143
|
+
"type": "string",
|
|
144
|
+
"minLength": 1
|
|
145
|
+
},
|
|
146
|
+
"concurrency": {
|
|
147
|
+
"type": "string",
|
|
148
|
+
"minLength": 1
|
|
149
|
+
},
|
|
150
|
+
"idempotency": {
|
|
151
|
+
"type": "string",
|
|
152
|
+
"minLength": 1
|
|
153
|
+
},
|
|
154
|
+
"cross_database_limit": {
|
|
155
|
+
"type": "string",
|
|
156
|
+
"minLength": 1
|
|
157
|
+
},
|
|
158
|
+
"timeouts": {
|
|
159
|
+
"type": "string",
|
|
160
|
+
"minLength": 1
|
|
161
|
+
},
|
|
162
|
+
"recovery": {
|
|
163
|
+
"type": "string",
|
|
164
|
+
"minLength": 1
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"required": [
|
|
168
|
+
"read_only",
|
|
169
|
+
"transaction_boundary",
|
|
170
|
+
"concurrency",
|
|
171
|
+
"idempotency",
|
|
172
|
+
"cross_database_limit",
|
|
173
|
+
"timeouts",
|
|
174
|
+
"recovery"
|
|
175
|
+
],
|
|
176
|
+
"additionalProperties": false
|
|
177
|
+
},
|
|
178
|
+
"test_seams": {
|
|
179
|
+
"type": "array",
|
|
180
|
+
"minItems": 1,
|
|
181
|
+
"items": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"properties": {
|
|
184
|
+
"seam_id": {
|
|
185
|
+
"type": "string",
|
|
186
|
+
"minLength": 1
|
|
187
|
+
},
|
|
188
|
+
"kind": {
|
|
189
|
+
"type": "string",
|
|
190
|
+
"minLength": 1
|
|
191
|
+
},
|
|
192
|
+
"subject_ref": {
|
|
193
|
+
"type": "string",
|
|
194
|
+
"minLength": 1
|
|
195
|
+
},
|
|
196
|
+
"assertion": {
|
|
197
|
+
"type": "string",
|
|
198
|
+
"minLength": 1
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
"required": [
|
|
202
|
+
"seam_id",
|
|
203
|
+
"kind",
|
|
204
|
+
"subject_ref",
|
|
205
|
+
"assertion"
|
|
206
|
+
],
|
|
207
|
+
"additionalProperties": false
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
"required": [
|
|
212
|
+
"scope_reason",
|
|
213
|
+
"impact_assessment",
|
|
214
|
+
"component_catalog",
|
|
215
|
+
"allowed_write_paths",
|
|
216
|
+
"read_dependencies",
|
|
217
|
+
"flow",
|
|
218
|
+
"failure_handling",
|
|
219
|
+
"consistency_policy",
|
|
220
|
+
"test_seams"
|
|
221
|
+
],
|
|
222
|
+
"additionalProperties": false,
|
|
223
|
+
"title": "既有工程的受控工程技术设计"
|
|
224
|
+
}
|