create-yss-spec 3.3.6 → 3.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/template/instance-runtime.js +8 -2
- package/src/validation/snapshot.js +7 -0
- package/template/.agents/skills/.strategic-design-skills-manifest.json +5 -3
- package/template/.agents/skills/archify/SKILL.md +1 -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/.codex/skills/archify/SKILL.md +1 -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/.cursor/skills/archify/SKILL.md +1 -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/.pi/skills/archify/SKILL.md +1 -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/docs/process/frontend-backend-delivery.md +7 -4
- package/template/docs/process/schemas/backend-delivery.schema.json +4 -0
- package/template/docs/process/schemas/frontend-delivery-acceptance-v1.schema.json +200 -0
- package/template/docs/process/schemas/frontend-delivery-acceptance.schema.json +37 -3
- 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-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-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 +37 -4
- package/template/docs/process/templates/lifecycle-checkpoint-template.yaml +1 -0
- package/template/docs/process/templates/stage-checkpoint-template.md +1 -0
- package/template/scripts/lib/approval-record.mjs +2 -1
- package/template/scripts/lib/backend-delivery.mjs +15 -3
- package/template/scripts/lib/frontend-delivery-boundary.mjs +20 -4
- package/template/scripts/lib/frontend-delivery.mjs +66 -2
- package/template/scripts/lib/strategic-feedback.mjs +33 -0
- package/template/scripts/lib/strategic-handoff-consumption.mjs +5 -0
- package/template/scripts/lib/strategic-handoff-io.mjs +1 -0
- package/template/scripts/lib/strategic-handoff.mjs +101 -10
- package/template/scripts/lib/user-decision-reuse.mjs +38 -0
- package/template/scripts/strategic-feedback +10 -0
- package/template/scripts/verify-frontend-strategic-preflight +12 -0
- package/template/skills-lock.json +10 -10
- package/template.manifest.json +1 -0
- package/template.snapshot.json +6 -5
package/template/.cursor/skills/yss-stage-decision/tests/fixtures/valid-stage-decision-package.yaml
CHANGED
|
@@ -1,16 +1,41 @@
|
|
|
1
|
-
schema_version:
|
|
1
|
+
schema_version: 3
|
|
2
2
|
stage_decision_id: stage-decision.supplier-admission
|
|
3
|
-
package_version:
|
|
3
|
+
package_version: v3
|
|
4
4
|
status: approved
|
|
5
5
|
problem_statement: 合规准入决定分散,采购无法稳定判断当前有效资格。
|
|
6
6
|
target_users: [采购专员、合规专员]
|
|
7
7
|
mvp: [提交供应商申请、合规准入决定、采购侧有效性校验]
|
|
8
8
|
non_goals: [供应商结算、采购付款、通用工作流平台]
|
|
9
|
-
success_criteria:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
success_criteria:
|
|
10
|
+
- id: success-criterion.current-admission
|
|
11
|
+
statement: 新采购订单 100% 校验当前有效准入决定。
|
|
12
|
+
source_refs: [rule.current-admission-required]
|
|
13
|
+
evidence_refs: [evidence.discovery.compliance]
|
|
14
|
+
status: confirmed
|
|
15
|
+
test_seams:
|
|
16
|
+
- id: test-seam.admission-validity-check
|
|
17
|
+
statement: admission-validity-check
|
|
18
|
+
source_refs: [scenario.admission-expires, invariant.current-admission-required]
|
|
19
|
+
evidence_refs: [evidence.discovery.compliance]
|
|
20
|
+
status: confirmed
|
|
21
|
+
confirmed_decisions:
|
|
22
|
+
- id: decision.compliance-owns-admission-rules
|
|
23
|
+
statement: ComplianceReview 拥有准入规则语义,ProcurementExecution 只消费决定。
|
|
24
|
+
source_refs: [rule.current-admission-required]
|
|
25
|
+
evidence_refs: [evidence.domain-strategy-review.supplier]
|
|
26
|
+
status: confirmed
|
|
27
|
+
assumptions:
|
|
28
|
+
- id: assumption.unique-subject-ref
|
|
29
|
+
statement: 供应商已有唯一 subject_ref。
|
|
30
|
+
source_refs: [scenario.supplier-submits]
|
|
31
|
+
evidence_refs: [evidence.discovery.supplier]
|
|
32
|
+
status: confirmed
|
|
33
|
+
constraints:
|
|
34
|
+
- id: constraint.preserve-procurement-flow
|
|
35
|
+
statement: 保留现有采购订单流程。
|
|
36
|
+
source_refs: [scenario.admission-expires]
|
|
37
|
+
evidence_refs: [evidence.discovery.compliance]
|
|
38
|
+
status: confirmed
|
|
14
39
|
unresolved_items:
|
|
15
40
|
- item: 供应商历史资料迁移范围
|
|
16
41
|
type: deferred
|
|
@@ -25,7 +50,7 @@ context_snapshot:
|
|
|
25
50
|
term_refs: [Global/Supplier, ComplianceReview/AdmissionDecision]
|
|
26
51
|
domain_strategy_ref:
|
|
27
52
|
domain_strategy_id: domain-strategy.supplier-admission
|
|
28
|
-
domain_version:
|
|
53
|
+
domain_version: v3
|
|
29
54
|
digest: <domain-strategy-digest>
|
|
30
55
|
status: approved
|
|
31
56
|
persisted_ref: domain-strategy.yaml
|
|
@@ -38,17 +63,21 @@ impact_assessment:
|
|
|
38
63
|
cross_repo: false
|
|
39
64
|
high_risk: false
|
|
40
65
|
downstream_mapping:
|
|
41
|
-
-
|
|
42
|
-
|
|
66
|
+
- mapping_id: mapping.backend-admission-validity
|
|
67
|
+
source_refs: [rule.current-admission-required, invariant.current-admission-required]
|
|
68
|
+
consumer_capability: backend-technical-design
|
|
43
69
|
propagation: direct
|
|
44
70
|
reapproval_condition: 领域策略版本或有效性规则变化
|
|
45
|
-
|
|
46
|
-
|
|
71
|
+
evidence_refs: [evidence.domain-strategy-review.supplier]
|
|
72
|
+
- mapping_id: mapping.frontend-admission-validity
|
|
73
|
+
source_refs: [scenario.admission-expires]
|
|
74
|
+
consumer_capability: frontend-engineering-design
|
|
47
75
|
propagation: transitive
|
|
48
76
|
reapproval_condition: Spec 基线变更
|
|
77
|
+
evidence_refs: [evidence.domain-strategy-review.supplier]
|
|
49
78
|
evidence_refs: [evidence.discovery.supplier, evidence.domain-strategy-review.supplier]
|
|
50
79
|
approval:
|
|
51
80
|
approval_ref: .agents/skills/yss-stage-decision/tests/fixtures/stage-decision-approval.yaml
|
|
52
81
|
approver: role.product-manager
|
|
53
82
|
persisted_ref: docs/.scratch/supplier/stage-decision/stage-decision-package-v1.yaml
|
|
54
|
-
current_version:
|
|
83
|
+
current_version: v3
|
package/template/.cursor/skills/yss-stage-decision/tests/fixtures/valid-supplier-domain.yaml
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
schema_version:
|
|
1
|
+
schema_version: 3
|
|
2
2
|
domain_strategy_id: domain-strategy.supplier-admission
|
|
3
|
-
domain_version:
|
|
3
|
+
domain_version: v3
|
|
4
4
|
status: approved
|
|
5
|
+
traceability_version: 1
|
|
6
|
+
rule_catalog:
|
|
7
|
+
- rule_id: rule.application-material-complete
|
|
8
|
+
statement: 申请材料必须完整
|
|
9
|
+
responsible_context: SupplierManagement
|
|
10
|
+
status: confirmed
|
|
11
|
+
evidence_refs: [evidence.discovery.supplier]
|
|
12
|
+
- rule_id: rule.current-admission-required
|
|
13
|
+
statement: 新采购订单必须引用当前有效的准入决定。
|
|
14
|
+
responsible_context: ComplianceReview
|
|
15
|
+
status: confirmed
|
|
16
|
+
evidence_refs: [evidence.discovery.compliance]
|
|
5
17
|
contexts:
|
|
6
18
|
- context_id: SupplierManagement
|
|
7
19
|
name: 供应商管理
|
|
@@ -64,6 +76,10 @@ scenarios:
|
|
|
64
76
|
preconditions: [供应商资料可编辑]
|
|
65
77
|
commands: [SubmitSupplierApplication]
|
|
66
78
|
rules: [申请材料必须完整]
|
|
79
|
+
rule_refs: [rule.application-material-complete]
|
|
80
|
+
critical: true
|
|
81
|
+
success_results: [完整申请进入合规审查]
|
|
82
|
+
evidence_refs: [evidence.discovery.supplier]
|
|
67
83
|
events: [SupplierApplicationSubmitted]
|
|
68
84
|
failure_results: [材料不完整时拒绝提交]
|
|
69
85
|
responsible_context: SupplierManagement
|
|
@@ -73,7 +89,11 @@ scenarios:
|
|
|
73
89
|
actor: compliance-officer
|
|
74
90
|
preconditions: [批准决定存在]
|
|
75
91
|
commands: [EvaluateAdmissionValidity]
|
|
76
|
-
rules: [
|
|
92
|
+
rules: [新采购订单必须引用当前有效的准入决定。]
|
|
93
|
+
rule_refs: [rule.current-admission-required]
|
|
94
|
+
critical: true
|
|
95
|
+
success_results: [过期准入决定不能支持新采购订单]
|
|
96
|
+
evidence_refs: [evidence.discovery.compliance]
|
|
77
97
|
events: [SupplierAdmissionExpired]
|
|
78
98
|
failure_results: [采购下单时资格校验失败]
|
|
79
99
|
responsible_context: ComplianceReview
|
|
@@ -94,6 +114,8 @@ invariants:
|
|
|
94
114
|
responsible_context: ComplianceReview
|
|
95
115
|
scenario_refs: [scenario.admission-expires]
|
|
96
116
|
verification_method: 领域场景测试和事件版本校验
|
|
117
|
+
rule_ref: rule.current-admission-required
|
|
118
|
+
evidence_refs: [evidence.discovery.compliance]
|
|
97
119
|
context_snapshot:
|
|
98
120
|
context_ref: CONTEXT.md
|
|
99
121
|
context_schema_version: 1
|
|
@@ -101,13 +123,23 @@ context_snapshot:
|
|
|
101
123
|
referenced_terms_digest: <referenced-terms-digest>
|
|
102
124
|
term_refs: [Global/Supplier, ComplianceReview/AdmissionDecision]
|
|
103
125
|
downstream_mapping:
|
|
104
|
-
-
|
|
126
|
+
- mapping_id: mapping.backend-admission-validity
|
|
127
|
+
source_refs: [rule.current-admission-required, invariant.current-admission-required]
|
|
128
|
+
consumer_capability: backend-technical-design
|
|
105
129
|
impacts: [spec, openapi, procurement-acceptance-tests]
|
|
106
130
|
propagation: stale
|
|
107
131
|
reapproval_condition: ComplianceReview 决定和有效期重新批准
|
|
132
|
+
evidence_refs: [evidence.discovery.compliance]
|
|
133
|
+
- mapping_id: mapping.frontend-admission-validity
|
|
134
|
+
source_refs: [scenario.admission-expires]
|
|
135
|
+
consumer_capability: frontend-engineering-design
|
|
136
|
+
impacts: [ui, frontend]
|
|
137
|
+
propagation: direct
|
|
138
|
+
reapproval_condition: 场景结果或视觉基线变化
|
|
139
|
+
evidence_refs: [evidence.discovery.compliance]
|
|
108
140
|
evidence_refs: [evidence.discovery.supplier, evidence.discovery.compliance]
|
|
109
141
|
approval:
|
|
110
142
|
approval_ref: .agents/skills/yss-stage-decision/tests/fixtures/domain-strategy-approval.yaml
|
|
111
143
|
approver: role.product-manager
|
|
112
144
|
persisted_ref: docs/.scratch/supplier/domain/domain-strategy-v1.yaml
|
|
113
|
-
current_version:
|
|
145
|
+
current_version: v3
|
|
@@ -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");
|
|
@@ -16,7 +16,7 @@ Create a self-contained, interactive HTML diagram from a small typed JSON specif
|
|
|
16
16
|
|
|
17
17
|
When the current repository contains `yss-project.yaml`, these rules override the upstream update and delivery commands below:
|
|
18
18
|
|
|
19
|
-
- Treat Archify as a conditional specialist. Use it only when the user or the current YSS contract explicitly requires an architecture, workflow, sequence, data-flow, lifecycle, or Mermaid-beautification artifact. A diagram is derived evidence; it never replaces Spec, ADR, OpenAPI,
|
|
19
|
+
- Treat Archify as a conditional specialist. Use it only when the user or the current YSS contract explicitly requires an architecture, workflow, sequence, data-flow, lifecycle, or Mermaid-beautification artifact. A diagram is derived evidence; it never replaces the active profile's architecture contract (such as backend Tactical Design or Frontend Engineering Design), Spec, ADR, OpenAPI, Slice Implementation Contract, review, or approval evidence.
|
|
20
20
|
- Do not run `scripts/check-update.mjs`. YSS pins the upstream revision in `skills-lock.json`; upgrades happen only through the repository's skill-maintenance workflow.
|
|
21
21
|
- Validate with the upstream `validate` command, but deliver through the repository-safe wrapper from the repository root:
|
|
22
22
|
|
|
@@ -24,13 +24,22 @@ description: 编排 Plan 到 Spec 入口的方案决策与业务边界、协作
|
|
|
24
24
|
|
|
25
25
|
Plan 的目标与退出条件由 `docs/process/lifecycle-registry.yaml` 持有;从 `docs/plan/templates/plan-template.md` 汇总输入。旧资产按 `docs/process/plan-migration.md` 重新整理并核查,关键未决项不得延期到 Spec,非关键项记录责任人、解决时点与接收方。
|
|
26
26
|
|
|
27
|
-
1. 读取 `yss-project.yaml`、`CONTEXT.md`、既有 Plan/Spec、ADR
|
|
27
|
+
1. 读取 `yss-project.yaml`、`CONTEXT.md`、既有 Plan/Spec、ADR 和当前 profile 的主索引/checkpoint;按 `yss-product-lifecycle` 的 `request-triage` 区分事实确认、产品决定、门禁确认和普通澄清。
|
|
28
28
|
2. 分离事实、决策、假设、约束和未决项;技术事实走 `yss-research` 的 `technical-evidence`,领域边界、业务规则、MVP、非目标、成功标准或阶段推进依据等决策证据走 `strategy-evidence`,市场/竞品事实走 `competitive-intelligence`。
|
|
29
29
|
3. 从业务故事、已发生的事实、规则、责任人和失败路径识别业务板块与业务责任区,不从数据库表或调用链直接反推边界。
|
|
30
30
|
4. 为每个业务责任区建立统一业务词汇;对跨责任区协作记录规则提供方、规则使用方、业务决策权、信息传递方向和口径转换负责人。
|
|
31
31
|
5. 记录待确认的关键业务对象,不提前指定技术模型。
|
|
32
|
-
6. 生成 schema
|
|
33
|
-
7. 运行 Schema
|
|
32
|
+
6. 生成 schema v3 `domain_strategy` 和 `stage_decision_package`,使用稳定规则、场景、决定、假设、约束、成功标准、测试 seam 和 downstream mapping ID,并以 `context_snapshot` 绑定根 `CONTEXT.md`、术语身份、完整文档 digest、引用术语 digest和证据。
|
|
33
|
+
7. 运行 Schema、唯一性、悬空引用、根路径、术语引用、digest、语义一致性和传播验证;发现关键冲突时返回 `blocked`,不得生成 `approved` 包。v2 仅只读;修改或重发必须使用 `scripts/migrate-contract-v3.mjs` 显式迁移为 `draft` 并重新批准。v1 字符串引用先用 `scripts/migrate-context-references.mjs` 迁移到 v2;歧义引用不得猜测。
|
|
34
|
+
|
|
35
|
+
## 控制面引用
|
|
36
|
+
|
|
37
|
+
- 用户决定遵循 `docs/process/lifecycle/references/user-decisions.md`:决定必须绑定资产、版本、范围和证据;范围、风险、摘要或失效条件变化后重新确认。
|
|
38
|
+
- checkpoint 是唯一机器状态源,业务 Ticket 只保存追踪引用,不复制阶段状态。
|
|
39
|
+
- 每次批准、重发和消费者流转前执行 `context_reconciliation`,核验 `CONTEXT.md` 的全文与引用术语双摘要。
|
|
40
|
+
- 技术事实与第三方行为走 `yss-research` 的 `technical-evidence`;产品策略依据走 `strategy-evidence`;市场与竞品判断走 `competitive-intelligence`。
|
|
41
|
+
- 修改本 Skill 时只编辑 `.agents/skills` 权威副本,再由 `maintaining-skills` 生成投影和 `skills-lock.json`。
|
|
42
|
+
- 本 Skill 只能标记影响、提出待解决问题和选择消费者能力;不得预选后端架构族,不得进入技术设计或实现流程,也不得授权实现。
|
|
34
43
|
|
|
35
44
|
## 语义方向规则
|
|
36
45
|
|
|
@@ -56,7 +65,7 @@ Plan 的目标与退出条件由 `docs/process/lifecycle-registry.yaml` 持有
|
|
|
56
65
|
- 不在业务方案设计阶段生成技术模型、生产代码或 API 契约。
|
|
57
66
|
- 不把模板 Fixture 当作具体项目的业务事实。
|
|
58
67
|
|
|
59
|
-
详细合同、字段和验证规则见 `references/domain-strategy-contract.md`、`references/stage-decision-package-contract.md` 与 `references/validation-rules.md
|
|
68
|
+
详细合同、字段和验证规则见 `references/domain-strategy-contract.md`、`references/stage-decision-package-contract.md` 与 `references/validation-rules.md`。当前机器可读合同分别为 `references/domain-strategy-v3.schema.json` 和 `references/stage-decision-package-v3.schema.json`;v2 schema 仅用于历史读取。对应验证器为 `scripts/validate-domain-strategy.mjs` 与 `scripts/validate-stage-decision-package.mjs`。
|
|
60
69
|
|
|
61
70
|
## 战略交接快照包
|
|
62
71
|
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## 顶层结构
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
当前机器可读合同使用 `references/domain-strategy-v3.schema.json`;`references/domain-strategy-v2.schema.json` 仅用于历史读取。顶层必须包含:
|
|
6
6
|
|
|
7
|
-
- `schema_version:
|
|
7
|
+
- `schema_version: 3`、`domain_strategy_id`、`domain_version`、`status`、`traceability_version: 1`;
|
|
8
|
+
- 带稳定 `rule_id` 与证据的 `rule_catalog`;
|
|
8
9
|
- `contexts`、`subdomains`、`relationships`、`scenarios`;
|
|
9
10
|
- `concept_candidates`、`invariants`、`context_snapshot`;
|
|
10
11
|
- `downstream_mapping`、`evidence_refs`、`approval`。
|
|
@@ -29,4 +30,4 @@
|
|
|
29
30
|
|
|
30
31
|
## 便携交付的逐条追溯
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
正式导出要求场景 `rule_refs / critical / success_results / evidence_refs` 和不变量 `rule_ref / evidence_refs`。`downstream_mapping` 必须使用稳定 `mapping_id`、来源 ID、消费者能力、影响项、传播规则和证据。已有 v2 文档继续只读兼容;修改或重发须显式迁移为 v3 `draft` 并重新批准。具体合同见 `docs/process/strategic-handoff-package.md`,不得由导出器发明业务身份。
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yss.local/schemas/domain-strategy-v2-compat.json",
|
|
4
|
+
"allOf": [
|
|
5
|
+
{"$ref": "domain-strategy.schema.json"},
|
|
6
|
+
{"properties": {"schema_version": {"const": 2}}, "required": ["schema_version"]}
|
|
7
|
+
]
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yss.local/schemas/domain-strategy-v3.json",
|
|
4
|
+
"allOf": [
|
|
5
|
+
{"$ref": "domain-strategy.schema.json"},
|
|
6
|
+
{"properties": {"schema_version": {"const": 3}}, "required": ["schema_version"]}
|
|
7
|
+
]
|
|
8
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://yss.local/schemas/domain-strategy-
|
|
3
|
+
"$id": "https://yss.local/schemas/domain-strategy-current.json",
|
|
4
4
|
"title": "YSS 业务边界与规则设计",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": ["schema_version", "domain_strategy_id", "domain_version", "status", "contexts", "subdomains", "relationships", "scenarios", "concept_candidates", "invariants", "context_snapshot", "downstream_mapping", "evidence_refs", "approval"],
|
|
7
7
|
"properties": {
|
|
8
8
|
"traceability_version": {"const": 1},
|
|
9
|
-
"rule_catalog": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["rule_id", "statement", "responsible_context", "status"], "properties": {"rule_id": {"type": "string", "pattern": "^rule\\.[a-z0-9][a-z0-9-]*$"}, "statement": {"type": "string", "minLength": 1}, "responsible_context": {"type": "string", "minLength": 1}, "status": {"const": "confirmed"}}}, "minItems": 1},
|
|
10
|
-
"schema_version": {"
|
|
9
|
+
"rule_catalog": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["rule_id", "statement", "responsible_context", "status"], "properties": {"rule_id": {"type": "string", "pattern": "^rule\\.[a-z0-9][a-z0-9-]*$"}, "statement": {"type": "string", "minLength": 1}, "responsible_context": {"type": "string", "minLength": 1}, "status": {"const": "confirmed"}, "evidence_refs": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}}}}, "minItems": 1},
|
|
10
|
+
"schema_version": {"enum": [2, 3]},
|
|
11
11
|
"domain_strategy_id": {"type": "string", "pattern": "^domain-strategy\\.[a-z0-9][a-z0-9-]*$"},
|
|
12
12
|
"domain_version": {"type": "string", "pattern": "^v[0-9]+$"},
|
|
13
13
|
"status": {"enum": ["draft", "ready-for-human", "approved", "stale", "blocked"]},
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"concept_candidates": {"type": "array", "items": {"$ref": "#/$defs/concept"}},
|
|
19
19
|
"invariants": {"type": "array", "items": {"$ref": "#/$defs/invariant"}},
|
|
20
20
|
"context_snapshot": {"$ref": "#/$defs/contextSnapshot"},
|
|
21
|
-
"downstream_mapping": {"type": "array"
|
|
21
|
+
"downstream_mapping": {"type": "array"},
|
|
22
22
|
"evidence_refs": {"type": "array", "minItems": 1, "items": {"type": "string", "minLength": 1}},
|
|
23
23
|
"approval": {"$ref": "#/$defs/approval"}
|
|
24
24
|
},
|
|
@@ -132,6 +132,20 @@
|
|
|
132
132
|
"reapproval_condition": {"type": "string", "minLength": 1}
|
|
133
133
|
}
|
|
134
134
|
},
|
|
135
|
+
"mappingV3": {
|
|
136
|
+
"type": "object",
|
|
137
|
+
"additionalProperties": false,
|
|
138
|
+
"required": ["mapping_id", "source_refs", "consumer_capability", "impacts", "propagation", "reapproval_condition", "evidence_refs"],
|
|
139
|
+
"properties": {
|
|
140
|
+
"mapping_id": {"type": "string", "pattern": "^mapping\\.[a-z0-9][a-z0-9-]*$"},
|
|
141
|
+
"source_refs": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "pattern": "^(rule|scenario|invariant)\\.[a-z0-9][a-z0-9-]*$"}},
|
|
142
|
+
"consumer_capability": {"enum": ["backend-technical-design", "frontend-engineering-design", "delivery-coordination"]},
|
|
143
|
+
"impacts": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}},
|
|
144
|
+
"propagation": {"enum": ["direct", "transitive", "not-applicable", "stale"]},
|
|
145
|
+
"reapproval_condition": {"type": "string", "minLength": 1},
|
|
146
|
+
"evidence_refs": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
135
149
|
"approval": {
|
|
136
150
|
"type": "object",
|
|
137
151
|
"required": ["approval_ref", "approver", "persisted_ref", "current_version"],
|
|
@@ -142,5 +156,61 @@
|
|
|
142
156
|
"current_version": {"type": "string", "pattern": "^v[0-9]+$"}
|
|
143
157
|
}
|
|
144
158
|
}
|
|
145
|
-
}
|
|
159
|
+
},
|
|
160
|
+
"allOf": [
|
|
161
|
+
{
|
|
162
|
+
"if": {"properties": {"schema_version": {"const": 3}}, "required": ["schema_version"]},
|
|
163
|
+
"then": {
|
|
164
|
+
"required": ["traceability_version", "rule_catalog"],
|
|
165
|
+
"properties": {
|
|
166
|
+
"traceability_version": {"const": 1},
|
|
167
|
+
"rule_catalog": {
|
|
168
|
+
"items": {
|
|
169
|
+
"required": ["evidence_refs"],
|
|
170
|
+
"properties": {
|
|
171
|
+
"evidence_refs": {
|
|
172
|
+
"type": "array",
|
|
173
|
+
"minItems": 1,
|
|
174
|
+
"uniqueItems": true,
|
|
175
|
+
"items": {"type": "string", "minLength": 1}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"scenarios": {
|
|
181
|
+
"items": {
|
|
182
|
+
"required": ["rule_refs", "critical", "success_results", "evidence_refs"],
|
|
183
|
+
"properties": {
|
|
184
|
+
"evidence_refs": {
|
|
185
|
+
"type": "array",
|
|
186
|
+
"minItems": 1,
|
|
187
|
+
"uniqueItems": true,
|
|
188
|
+
"items": {"type": "string", "minLength": 1}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
"invariants": {
|
|
194
|
+
"items": {
|
|
195
|
+
"required": ["rule_ref", "evidence_refs"],
|
|
196
|
+
"properties": {
|
|
197
|
+
"evidence_refs": {
|
|
198
|
+
"type": "array",
|
|
199
|
+
"minItems": 1,
|
|
200
|
+
"uniqueItems": true,
|
|
201
|
+
"items": {"type": "string", "minLength": 1}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"downstream_mapping": {"items": {"$ref": "#/$defs/mappingV3"}}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
"else": {
|
|
210
|
+
"properties": {
|
|
211
|
+
"downstream_mapping": {"items": {"$ref": "#/$defs/mapping"}}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
]
|
|
146
216
|
}
|
package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-contract.md
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
## 必须包含
|
|
6
6
|
|
|
7
|
-
- 问题陈述、目标用户、MVP
|
|
8
|
-
-
|
|
7
|
+
- 问题陈述、目标用户、MVP、非目标,以及带稳定 ID、来源 ID 和证据的成功标准与可执行测试 seam;
|
|
8
|
+
- 带稳定 ID、来源 ID 和证据的已确认决策、假设、约束,以及有责任人的未决项;
|
|
9
9
|
- `context_snapshot`:只引用根 `CONTEXT.md`,并绑定结构化术语身份、全文摘要和引用集摘要;
|
|
10
10
|
- `domain_strategy_ref`:领域战略合同的稳定 ID、版本、digest 和批准状态;
|
|
11
11
|
- UI/API/Data/Backend/Frontend/跨仓/高风险影响面布尔值;
|
|
12
|
-
-
|
|
12
|
+
- 每个消费者能力的稳定 `mapping_id`、领域来源 ID、传播方式、重新批准条件、证据引用和批准记录。`approval.approval_ref` 必须指向可读取且通过 `scripts/verify-approval-record` 的 `gate.stage-decision-package-approved` 会签记录;`approval.approver` 必须与记录中的 `role_id` 一致。
|
|
13
13
|
|
|
14
14
|
## 未决项规则
|
|
15
15
|
|
|
@@ -19,4 +19,4 @@
|
|
|
19
19
|
|
|
20
20
|
只有 `approved` 且引用的领域战略为 `approved`、版本当前的阶段包,才可以进入 Spec synthesis。任何领域战略 digest、版本或影响面变化都使阶段包 `stale`,并要求重新评估。
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
新写入阶段包使用 `schema_version: 3`,且只能引用 Domain Strategy v3。v2 仅只读;修改或重新交付须用 `scripts/migrate-contract-v3.mjs` 生成未批准的 `draft` 后补齐来源并重新批准。旧版字符串路径或 Markdown 锚点先通过上下文迁移器读取;无法唯一映射到 `<ContextId>/<EnglishIdentifier>` 时返回 `migration-required`,不得猜测。
|
package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-v2.schema.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yss.local/schemas/stage-decision-package-v2-compat.json",
|
|
4
|
+
"allOf": [
|
|
5
|
+
{"$ref": "stage-decision-package.schema.json"},
|
|
6
|
+
{"properties": {"schema_version": {"const": 2}}, "required": ["schema_version"]}
|
|
7
|
+
]
|
|
8
|
+
}
|
package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-v3.schema.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://yss.local/schemas/stage-decision-package-v3.json",
|
|
4
|
+
"allOf": [
|
|
5
|
+
{"$ref": "stage-decision-package.schema.json"},
|
|
6
|
+
{"properties": {"schema_version": {"const": 3}}, "required": ["schema_version"]}
|
|
7
|
+
]
|
|
8
|
+
}
|