create-yss-spec 3.4.3 → 3.4.5
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 +1 -1
- package/package.json +2 -2
- package/template/.agents/skills/.strategic-design-skills-manifest.json +3 -3
- package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
- package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.agents/skills/yss-layered-mvc-scaffold-generator/SKILL.md +1 -1
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +22 -5
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.agents/skills/yss-product-lifecycle/references/user-decisions.md +1 -1
- package/template/.agents/skills/yss-stage-decision/SKILL.md +1 -1
- package/template/.agents/skills/yss-stage-decision/references/domain-strategy-contract.md +2 -0
- package/template/.agents/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.agents/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +3 -3
- package/template/.agents/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +3 -3
- package/template/.agents/skills/yss-stage-decision/tests/run-scenarios.mjs +33 -0
- package/template/.agents/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.agents/skills/yss-technical-design/SKILL.md +1 -1
- package/template/.agents/skills/yss-technical-design/references/technical-design-contract.md +1 -1
- package/template/.agents/skills/yss-technical-design/tests/run-scenarios.mjs +1 -1
- package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
- package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.codex/skills/yss-layered-mvc-scaffold-generator/SKILL.md +1 -1
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +22 -5
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.codex/skills/yss-product-lifecycle/references/user-decisions.md +1 -1
- package/template/.codex/skills/yss-stage-decision/SKILL.md +1 -1
- package/template/.codex/skills/yss-stage-decision/references/domain-strategy-contract.md +2 -0
- package/template/.codex/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.codex/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +3 -3
- package/template/.codex/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +3 -3
- package/template/.codex/skills/yss-stage-decision/tests/run-scenarios.mjs +33 -0
- package/template/.codex/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.codex/skills/yss-technical-design/SKILL.md +1 -1
- package/template/.codex/skills/yss-technical-design/references/technical-design-contract.md +1 -1
- package/template/.codex/skills/yss-technical-design/tests/run-scenarios.mjs +1 -1
- package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
- package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.cursor/skills/yss-layered-mvc-scaffold-generator/SKILL.md +1 -1
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +22 -5
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.cursor/skills/yss-product-lifecycle/references/user-decisions.md +1 -1
- package/template/.cursor/skills/yss-stage-decision/SKILL.md +1 -1
- package/template/.cursor/skills/yss-stage-decision/references/domain-strategy-contract.md +2 -0
- package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +3 -3
- package/template/.cursor/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +3 -3
- package/template/.cursor/skills/yss-stage-decision/tests/run-scenarios.mjs +33 -0
- package/template/.cursor/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.cursor/skills/yss-technical-design/SKILL.md +1 -1
- package/template/.cursor/skills/yss-technical-design/references/technical-design-contract.md +1 -1
- package/template/.cursor/skills/yss-technical-design/tests/run-scenarios.mjs +1 -1
- package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +2 -2
- package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +1 -1
- package/template/.pi/skills/yss-layered-mvc-scaffold-generator/SKILL.md +1 -1
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +22 -5
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +1 -1
- package/template/.pi/skills/yss-product-lifecycle/references/user-decisions.md +1 -1
- package/template/.pi/skills/yss-stage-decision/SKILL.md +1 -1
- package/template/.pi/skills/yss-stage-decision/references/domain-strategy-contract.md +2 -0
- package/template/.pi/skills/yss-stage-decision/references/stage-decision-package-contract.md +1 -1
- package/template/.pi/skills/yss-stage-decision/scripts/validate-domain-strategy.mjs +3 -3
- package/template/.pi/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs +3 -3
- package/template/.pi/skills/yss-stage-decision/tests/run-scenarios.mjs +33 -0
- package/template/.pi/skills/yss-tactical-design/SKILL.md +1 -1
- package/template/.pi/skills/yss-technical-design/SKILL.md +1 -1
- package/template/.pi/skills/yss-technical-design/references/technical-design-contract.md +1 -1
- package/template/.pi/skills/yss-technical-design/tests/run-scenarios.mjs +1 -1
- package/template/docs/agents/digital-human-roles.yaml +5 -1
- package/template/docs/architecture/templates/engineering-baseline-review-template.md +6 -6
- package/template/docs/engineering/backend-platforms.md +1 -1
- package/template/docs/process/existing-ui-baseline.md +1 -1
- package/template/docs/process/lifecycle-artifact-map.md +3 -2
- package/template/docs/process/lifecycle-registry-baseline.json +2 -1
- package/template/docs/process/lifecycle-registry.yaml +13 -4
- package/template/docs/process/schemas/digital-human-task-package.schema.json +1 -0
- package/template/docs/process/schemas/lifecycle-checkpoint.schema.json +4 -0
- package/template/docs/process/schemas/review-bundle.schema.json +42 -0
- package/template/docs/process/strategic-handoff-package.md +5 -11
- package/template/docs/templates/build-architecture-checklist-template.md +2 -2
- package/template/docs/templates/implementation-routing-template.md +4 -4
- package/template/docs/templates/review-bundle-template.yaml +26 -0
- package/template/scripts/lib/approval-record.mjs +25 -6
- package/template/scripts/lib/strategic-handoff-io.mjs +7 -0
- package/template/scripts/lib/strategic-handoff.mjs +21 -7
- package/template/scripts/lib/user-decision.mjs +13 -2
- package/template/skills-lock.json +13 -13
- package/template.snapshot.json +5 -5
|
@@ -3,7 +3,7 @@ import { readFile } from "node:fs/promises";
|
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { parseArgs } from "node:util";
|
|
5
5
|
import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
|
|
6
|
-
import { loadApprovalRecord, resolveApprovalRef,
|
|
6
|
+
import { loadApprovalRecord, resolveApprovalRef, validateApprovalRecord } from "../../../../scripts/lib/approval-record.mjs";
|
|
7
7
|
import { verifyContextSnapshot } from "../../../../scripts/lib/context-contract.mjs";
|
|
8
8
|
|
|
9
9
|
import { extractTraceability } from "../../../../scripts/lib/strategic-handoff-rules.mjs";
|
|
@@ -196,8 +196,8 @@ function validate(data, contextRoot) {
|
|
|
196
196
|
if (approval.current_version !== data.domain_version) errors.push("approval.current_version 必须等于 domain_version");
|
|
197
197
|
try {
|
|
198
198
|
const approvalPath = resolveApprovalRef(approval.approval_ref);
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
const record = loadApprovalRecord(approvalPath, "check.domain-strategy-approved");
|
|
200
|
+
validateApprovalRecord(record, { requireApproved: true });
|
|
201
201
|
if (record.gate_id !== "check.domain-strategy-approved") errors.push("approval.approval_ref 的 gate_id 必须为 check.domain-strategy-approved");
|
|
202
202
|
if (record.role_id !== approval.approver) errors.push("approval.approver 必须与会签记录 role_id 一致");
|
|
203
203
|
} catch (error) { errors.push(`approval.approval_ref 会签记录无效: ${error.message}`); }
|
package/template/.codex/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { resolve } from "node:path";
|
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
7
7
|
import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
|
|
8
|
-
import { loadApprovalRecord, resolveApprovalRef,
|
|
8
|
+
import { loadApprovalRecord, resolveApprovalRef, validateApprovalRecord } from "../../../../scripts/lib/approval-record.mjs";
|
|
9
9
|
import { verifyContextSnapshot } from "../../../../scripts/lib/context-contract.mjs";
|
|
10
10
|
|
|
11
11
|
const required = ["schema_version", "stage_decision_id", "package_version", "status", "problem_statement", "target_users", "mvp", "non_goals", "success_criteria", "test_seams", "confirmed_decisions", "assumptions", "constraints", "unresolved_items", "context_snapshot", "domain_strategy_ref", "impact_assessment", "downstream_mapping", "evidence_refs", "approval"];
|
|
@@ -129,8 +129,8 @@ async function validate(data, contextRoot) {
|
|
|
129
129
|
if (data.status === "approved" && nonEmpty(approval.approval_ref)) {
|
|
130
130
|
try {
|
|
131
131
|
const approvalPath = resolveApprovalRef(approval.approval_ref);
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
const record = loadApprovalRecord(approvalPath, "check.stage-decision-package-approved");
|
|
133
|
+
validateApprovalRecord(record, { requireApproved: true });
|
|
134
134
|
if (record.gate_id !== "check.stage-decision-package-approved") errors.push("approval_ref 的 gate_id 必须为 check.stage-decision-package-approved");
|
|
135
135
|
if (record.role_id !== approval.approver) errors.push("approval.approver 必须与会签记录 role_id 一致");
|
|
136
136
|
} catch (error) { errors.push(`approval_ref 会签记录无效: ${error.message}`); }
|
|
@@ -201,6 +201,39 @@ try {
|
|
|
201
201
|
const packagePass = run(packageValidator, packageFile, temporaryRoot);
|
|
202
202
|
if (packagePass.status !== 0) throw new Error(`valid v3 stage decision package should pass: ${packagePass.stderr}`);
|
|
203
203
|
|
|
204
|
+
const bundleFile = join(temporaryRoot, "plan-review-bundle.json");
|
|
205
|
+
const bundledDomainValue = parseYaml(domainSource);
|
|
206
|
+
bundledDomainValue.approval.approval_ref = bundleFile;
|
|
207
|
+
const bundledDomainSource = JSON.stringify(bundledDomainValue, null, 2);
|
|
208
|
+
const bundledDomainFile = join(temporaryRoot, "domain-strategy-bundled.yaml");
|
|
209
|
+
await writeFile(bundledDomainFile, bundledDomainSource);
|
|
210
|
+
const bundledPackageValue = parseYaml(packageSource);
|
|
211
|
+
bundledPackageValue.domain_strategy_ref.persisted_ref = "domain-strategy-bundled.yaml";
|
|
212
|
+
bundledPackageValue.domain_strategy_ref.digest = digestYaml(bundledDomainSource);
|
|
213
|
+
bundledPackageValue.approval.approval_ref = bundleFile;
|
|
214
|
+
const bundledPackageSource = JSON.stringify(bundledPackageValue, null, 2);
|
|
215
|
+
const bundledPackageFile = join(temporaryRoot, "stage-decision-bundled.yaml");
|
|
216
|
+
await writeFile(bundledPackageFile, bundledPackageSource);
|
|
217
|
+
await writeFile(bundleFile, JSON.stringify({
|
|
218
|
+
schema_version: 1,
|
|
219
|
+
kind: "review-bundle",
|
|
220
|
+
bundle_id: "review-bundle.plan",
|
|
221
|
+
task_id: "task.plan-review.supplier-admission",
|
|
222
|
+
work_unit_id: "work-unit.plan-requirements",
|
|
223
|
+
review_session_id: "review-session.plan.supplier-admission",
|
|
224
|
+
role_id: "role.product-manager",
|
|
225
|
+
runtime_id: "runtime.generic",
|
|
226
|
+
principal_ref: "instance:role.product-manager",
|
|
227
|
+
reviews: [
|
|
228
|
+
{ schema_version: 1, gate_id: "check.domain-strategy-approved", decision: "approved", actor_kind: "digital-human", role_id: "role.product-manager", runtime_id: "runtime.generic", principal_ref: "instance:role.product-manager", drafter_role_id: "role.requirements-manager", drafter_principal_ref: "instance:role.requirements-manager", subject_ref: bundledDomainFile, subject_digest: digestYaml(bundledDomainSource).slice(7), approval_scope: ["feature.supplier-admission"], evidence_refs: [bundledDomainFile] },
|
|
229
|
+
{ schema_version: 1, gate_id: "check.stage-decision-package-approved", decision: "approved", actor_kind: "digital-human", role_id: "role.product-manager", runtime_id: "runtime.generic", principal_ref: "instance:role.product-manager", drafter_role_id: "role.requirements-manager", drafter_principal_ref: "instance:role.requirements-manager", subject_ref: bundledPackageFile, subject_digest: digestYaml(bundledPackageSource).slice(7), approval_scope: ["feature.supplier-admission"], evidence_refs: [bundledPackageFile] }
|
|
230
|
+
]
|
|
231
|
+
}, null, 2));
|
|
232
|
+
const bundledDomainPass = run(validator, bundledDomainFile, temporaryRoot);
|
|
233
|
+
if (bundledDomainPass.status !== 0) throw new Error(`domain strategy should select its conclusion from Plan review-bundle: ${bundledDomainPass.stderr}`);
|
|
234
|
+
const bundledPackagePass = run(packageValidator, bundledPackageFile, temporaryRoot);
|
|
235
|
+
if (bundledPackagePass.status !== 0) throw new Error(`stage decision should select its conclusion from Plan review-bundle: ${bundledPackagePass.stderr}`);
|
|
236
|
+
|
|
204
237
|
const v2Stage = toV2Stage(packageSource, digestYaml(v2DomainSource));
|
|
205
238
|
const v2StageFile = join(temporaryRoot, "stage-decision-v2.yaml");
|
|
206
239
|
await writeFile(v2StageFile, JSON.stringify(v2Stage, null, 2));
|
|
@@ -9,7 +9,7 @@ description: 在 YSS 技术分析阶段将批准的战略领域输入细化为
|
|
|
9
9
|
|
|
10
10
|
## 适用边界
|
|
11
11
|
|
|
12
|
-
- 由 `yss-technical-design` 在已确认 `domain-driven`
|
|
12
|
+
- 由 `yss-technical-design` 在已确认 `domain-driven` 的技术设计分支中调用;新建后端必须先通过 `gate.backend-architecture-platform-approved`,由用户在同一次决定中确认 DDD / MVC 与精确 Spring Boot 版本。传统 MVC 使用 `yss-mvc-design`;既有工程直接核验并复用当前登记架构及固定工程基线/POM 中的实际 Spring Boot 版本,不重复询问。不得按状态、一致性影响、目录或默认值单独推断为 DDD。
|
|
13
13
|
- 输入必须是版本当前的 Spec、功能架构、战略 DDD、状态矩阵、OpenAPI Draft / Freeze、ADR 和工程约束。若输入来自 Strategic Design Handoff,必须先用 `scripts/verify-strategic-context-import` 验证历史 v3/v4 或当前 v5 的 `source_context_snapshot` / `context_delta` 已对账到目标仓根 `CONTEXT.md`,对应的 prototype 或 existing UI baseline 可读取且摘要当前,并且目标侧 `context_reconciliation` 有效;未完成时不得开始战术建模。
|
|
14
14
|
- 默认将结果写入系统概要设计 / 数据架构中的 Tactical DDD Check;聚合、状态机、一致性或持久化映射复杂到无法清楚表达时,才升级为独立战术设计文档。
|
|
15
15
|
- 没有聚合、状态、不变量、一致性或领域边界影响时返回 `not-applicable` 及原因,不生成空设计。
|
|
@@ -17,7 +17,7 @@ description: 在 YSS 技术分析中统一承接需求与战略输入,按已
|
|
|
17
17
|
|
|
18
18
|
先读根 `CONTEXT.md`、已批准且当前的 Spec、业务规则、关键场景、适用的 API 契约、ADR 和工程约束。没有 API 或其他专项影响时记录有依据的不适用,不生成占位设计。
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
按项目绑定架构选择的来源及摘要。新工程必须先通过 `gate.backend-architecture-platform-approved`:Agent 展示 DDD / MVC 推荐依据及平台清单中的精确 Spring Boot、Java 版本,用户在同一次决定中确认两项内容;决定持久化到 `scaffold-architecture-decisions.yaml`,再进入对应分支,后续脚手架消费同一决定。既有工程核验并沿用当前登记架构及固定工程基线/POM 中的实际 Spring Boot 版本,该门禁记录为 `not-applicable`,不重复询问;架构转换或平台升级另行立项。只有 `domain-driven` 和 `layered-mvc` 两种架构族,不能从目录推断或默认 DDD、MVC 或 Spring Boot 版本。具体 Profile 及模块边界消费技能注册表与 `docs/agents/backend-architecture-profiles.md`。
|
|
21
21
|
|
|
22
22
|
- `domain-driven`:调用 `yss-tactical-design`,补齐适用的战略领域输入。
|
|
23
23
|
- `layered-mvc`:调用 `yss-mvc-design`,不要求战略 DDD、聚合、值对象、Domain Event 或 DDD Gateway。
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
## 共同头
|
|
6
6
|
|
|
7
7
|
- `schema_version: 2`、`technical_design_id: technical-design.<name>`、`version: vN`、`status`、`context_ref: CONTEXT.md`。
|
|
8
|
-
- `architecture`:`family`、`project_id`、`source_kind: scaffold-decision | existing-registration`、`decision_ref`、`decision_digest`。新项目引用正式且 current
|
|
8
|
+
- `architecture`:`family`、`project_id`、`source_kind: scaffold-decision | existing-registration`、`decision_ref`、`decision_digest`。新项目引用正式且 current 的脚手架决定,所选项目必须已通过 `gate.backend-architecture-platform-approved`,用户决定同时绑定 DDD / MVC、平台 Profile、精确 Spring Boot 与 Java 版本;既有登记引用当前 `project_id` 和 `architecture_identity.architecture_family`,并从固定工程基线/POM 复用实际 Spring Boot 版本,不重新询问。架构或平台来源变化须重新绑定和审查,不能改合同字段冒充用户改选或升级。
|
|
9
9
|
- `inputs`:每行 `{kind, ref, version, digest}`,kind 为 context/spec/rules/scenarios/api/adr/engineering/strategic;至少包含根 CONTEXT.md 与 Spec。适用的工程/API 约束同样绑定。无 API 影响理由记录在需求或工程输入中。DDD 另须 strategic 输入,MVC 不要求。
|
|
10
10
|
- `source_items`:无战略包时从批准需求提取稳定规则和场景 `{source_id, kind: rule | scenario, critical, source_ref}`。source_ref 必须对应 inputs,不复制源正文成为第二事实源。
|
|
11
11
|
- `traceability`:逐项对应 source_items。沿用 `tactical_refs` 字段名以兼容承接协议,其值在新合同中可指向 MVC 用例、规则或 DDD 对象;其他字段与战略承接 rows 相同。implemented 仅表示设计承接已落实,不表示代码已实现。
|
|
@@ -56,7 +56,7 @@ try {
|
|
|
56
56
|
ddd.design.aggregate_catalog[0].api_exposure = 'public'; ddd.digest = technicalDigest(ddd);
|
|
57
57
|
await assert.rejects(() => validate(ddd), /internal-only/); checks++;
|
|
58
58
|
const scaffold = mvcFixture(root);
|
|
59
|
-
const decision = attachScaffoldDecisionFixture(path.join(root, 'decision-evidence'), { project_id: 'example', status: 'user-confirmed', confirmed_architecture: 'layered-mvc', decision_inputs_digest: `sha256:${'1'.repeat(64)}`, user_confirmation: { confirmation_ref: 'user-message', confirmed_by: 'user' } });
|
|
59
|
+
const decision = attachScaffoldDecisionFixture(path.join(root, 'decision-evidence'), { project_id: 'example', status: 'user-confirmed', confirmed_architecture: 'layered-mvc', platform_profile: 'spring-boot-2.7-jdk8', decision_inputs_digest: `sha256:${'1'.repeat(64)}`, user_confirmation: { confirmation_ref: 'user-message', confirmed_by: 'user' } });
|
|
60
60
|
const record = { status: 'current', template: false, decisions: [decision] };
|
|
61
61
|
const recordFile = path.join(root, 'decision.json');
|
|
62
62
|
writeFileSync(recordFile, JSON.stringify(record));
|
|
@@ -23,7 +23,7 @@ description: 用于生成完整的 YSS DDD 多模块后端脚手架。当用户
|
|
|
23
23
|
|
|
24
24
|
## Spring Boot / Java 平台选择
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
调用本技能前由生命周期编排器展示 `scripts/backend-platforms` 的精确版本清单及兼容状态,并通过 `gate.backend-architecture-platform-approved` 把架构、Spring Boot、Java 和 YSS 父 POM/BOM 合并展示、取得真实用户确认;生成器不提问、不猜版本、不使用 `x` 或 `latest`。已有批准且当前的选择展示摘要后复用;既有工程核验并复用登记值,不触发该门禁。
|
|
27
27
|
|
|
28
28
|
- 候选平台:Boot 2.7.18 / Java 8,Boot 3.5.16 / Java 17 或 21,Boot 4.1.1 / Java 17 或 21。新 Boot 默认推荐 Java 17;候选不等于可生成。
|
|
29
29
|
- 独立子项目可继承主项目组合或覆盖,必须逐项目确认(允许一次确认明确列出的项目);同一 Maven Reactor 使用一个平台。
|
|
@@ -36,7 +36,7 @@ description: 用于生成完整的 YSS DDD 多模块后端脚手架。当用户
|
|
|
36
36
|
|
|
37
37
|
## 优先流程
|
|
38
38
|
|
|
39
|
-
1. 确认服务级 `scaffold_request_id
|
|
39
|
+
1. 确认服务级 `scaffold_request_id`、已通过 `gate.backend-architecture-platform-approved` 的 `domain-driven` 架构与精确 Spring Boot 版本选择及 digest、项目名、基础包名、Maven 项目坐标、父 POM GAV、YSS Components BOM 版本、输出目录和批准 Profile。Java `base_package` 与 Maven `group_id` 是两个独立输入,不得相互推导;脚手架发生在 Ticket 正式化前,不使用 `slice_id` 伪造切片身份。
|
|
40
40
|
Harness 内输出目录必须是 `apps/backend/` 容器,生成器再以 `project_name` 创建 `apps/backend/<project>/`;禁止使用 `app/backend/`、`app/frontend/` 或把 `apps/backend/` 之外的容器根当作后端项目根。
|
|
41
41
|
2. 优先运行 `node scripts/generate_and_verify_scaffold.mjs`,在同一个受控工作流中生成骨架并执行真实 Maven 验证。`generate_scaffold.mjs` 只是底层生成原语,单独返回 0 不代表脚手架完成。
|
|
42
42
|
3. 检查生成的模块名、POM、机械启动入口、基础配置文件和包路径。
|
|
@@ -47,7 +47,7 @@ description: "编译或重验 YSS Slice Implementation Contract、最小 Skill
|
|
|
47
47
|
- Harness 内实现路径必须落在 `apps/backend/<project>/` 或 `apps/frontend/<project>/` 的具体项目目录;`apps/backend/`、`apps/frontend/` 只能作为容器,`app/backend/`、`app/frontend/` 及其子路径一律阻断。外部实现仓库使用其登记的真实项目根路径。`git-submodule` 使用 `implementation_path_policy: git-submodule-harness-apps`,空 gitlink、detached HEAD 或 `--force` 覆盖挂载点不得脚手架;`inspectWorkingTreeScope.writable` 必须为显式布尔值。
|
|
48
48
|
- 当前用户、缓存、审计、Excel、分布式 ID、请求校验、错误映射、加解密或网关韧性命中时,必须按 `compiler-contract.yaml` 的 `impact_to_capabilities` 补齐入口 capability;不能只在 `boundaries.md` 中提及。仅复用已经验证的平台认证 / 授权能力不算 component impact,不自动增加权限专项 skill。
|
|
49
49
|
- 业务行为使用 `behavior-tdd`;只有机械脚手架/生成物可用 `controlled-generation`,并记录例外和验证。
|
|
50
|
-
- 阶段 5 若命中交付面且无已有工程,按 Project Scaffold Contract schema v4 编译 `controlled-generation` 合同 draft
|
|
50
|
+
- 阶段 5 若命中交付面且无已有工程,按 Project Scaffold Contract schema v4 编译 `controlled-generation` 合同 draft。后端先读取已通过 `gate.backend-architecture-platform-approved` 的架构与精确 Spring Boot 版本决定,并以原始字节 digest 绑定批准且当前的 Technical Design、Data Architecture Decision v1、API Contract Decision v1 及 `gate.engineering-contract-approved` 真实批准记录;编译器不得自行默认、提问或批准。既有工程核验并复用当前登记架构及固定工程基线/POM 中的实际版本,不重新询问或生成。API `required` 时工程批准还必须直接绑定冻结 OpenAPI YAML 的版本与摘要,`not-applicable` 时必须有影响评估、明确原因和证据。前端绑定标准模板精确 commit、应用标识、路由、OpenAPI 影响、目标路径和 `init_git` 决定。合同经生命周期批准并持久化后才能运行生成器。历史后端 schema v3 只允许 Manifest 只读恢复审计,并须补齐 API 对账,不得新生成;前端只接受 v4。生成与验证完成、仓库登记并通过 `check.implementation-repositories-ready` 后,才编译 Ticket 与业务 Slice Contract。
|
|
51
51
|
- 脚手架合同在编译阶段只能是 `draft` / `ready-for-lifecycle-review` / `blocked`;只有生命周期编排器可以把已持久化脚手架合同标记为 `approved`。脚手架合同只覆盖业务代码前的工程骨架工作单元;生成、基线校验和合同重编译完成后,它不能替代脚手架后的 Slice Implementation Contract。
|
|
52
52
|
- 脚手架输出消费批准的脚手架合同;脚手架后的所有生成后端代码都必须绑定当前批准且版本当前的 Slice Implementation Contract、主 YSS skill、依赖闭包、允许写路径、预期证据和 YSS Skill Execution Result。打印命令、`./mvnw validate` 单项通过或脚手架成功不能替代合同批准;生成范围从机械内容变成业务行为时触发完整重路由。
|
|
53
53
|
- 专项结果中的越界路径、缺失证据、`drift`、`violation` 或 `new_impacts` 必须阻断或重路由。
|
|
@@ -18,7 +18,7 @@ description: 用于在生命周期已批准的脚手架合同下生成按批准
|
|
|
18
18
|
|
|
19
19
|
## Spring Boot / Java 平台选择
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
调用本技能前由生命周期编排器展示 `scripts/backend-platforms` 的精确版本清单及兼容状态,并通过 `gate.backend-architecture-platform-approved` 把架构、Spring Boot、Java 和 YSS 父 POM/BOM 合并展示、取得真实用户确认;生成器不提问、不猜版本、不使用 `x` 或 `latest`。已有批准且当前的选择展示摘要后复用;既有工程核验并复用登记值,不触发该门禁。
|
|
22
22
|
|
|
23
23
|
- 候选平台:Boot 2.7.18 / Java 8,Boot 3.5.16 / Java 17 或 21,Boot 4.1.1 / Java 17 或 21。新 Boot 默认推荐 Java 17;候选不等于可生成。
|
|
24
24
|
- 独立子项目可继承主项目组合或覆盖,必须逐项目确认(允许一次确认明确列出的项目);同一 Maven Reactor 使用一个平台。
|
package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml
CHANGED
|
@@ -382,7 +382,15 @@ work_unit_routes:
|
|
|
382
382
|
technical_design:
|
|
383
383
|
applies_when: backend_delivery_impact
|
|
384
384
|
new_backend_repository: required
|
|
385
|
-
architecture_source:
|
|
385
|
+
architecture_source: new-project-user-gate-or-current-existing-registration-before-branch-design
|
|
386
|
+
pre_design_gate:
|
|
387
|
+
id: gate.backend-architecture-platform-approved
|
|
388
|
+
applies_when: new_backend_repository
|
|
389
|
+
confirms: [architecture_family, exact_spring_boot_version]
|
|
390
|
+
architecture_choices: [domain-driven, layered-mvc]
|
|
391
|
+
platform_source: docs/engineering/backend-platforms.json
|
|
392
|
+
existing_repository: not-applicable-reuse-current-registration
|
|
393
|
+
missing_or_stale: blocked
|
|
386
394
|
branches:
|
|
387
395
|
domain-driven: yss-tactical-design
|
|
388
396
|
layered-mvc: yss-mvc-design
|
|
@@ -414,6 +422,7 @@ work_unit_routes:
|
|
|
414
422
|
placeholder_assets: forbidden
|
|
415
423
|
atomic_approval_gate: gate.engineering-contract-approved
|
|
416
424
|
human_gate: gate.engineering-contract-approved
|
|
425
|
+
entry_user_gate: gate.backend-architecture-platform-approved
|
|
417
426
|
applies_when: technical_or_contract_impact
|
|
418
427
|
not_applicable_reason: no_technical_or_contract_impact
|
|
419
428
|
work-unit.implementation-repository-preparation:
|
|
@@ -771,7 +780,8 @@ scaffold_architecture_decision:
|
|
|
771
780
|
applies_when: [backend_impact, scaffold_status_required]
|
|
772
781
|
owner: yss-product-lifecycle
|
|
773
782
|
stage: work-unit.technical-analysis
|
|
774
|
-
|
|
783
|
+
gate: gate.backend-architecture-platform-approved
|
|
784
|
+
timing: after-impact-and-platform-candidate-resolution-before-ddd-or-mvc-branch-design
|
|
775
785
|
source: scaffold-architecture-decisions.yaml
|
|
776
786
|
schema_version: 1
|
|
777
787
|
statuses: [undecided, recommended, awaiting-user-decision, user-confirmed, lifecycle-approved, consumed, stale]
|
|
@@ -782,6 +792,12 @@ scaffold_architecture_decision:
|
|
|
782
792
|
layered-mvc:
|
|
783
793
|
display_name: MVC 开发脚手架
|
|
784
794
|
recommendation_signals: [crud, reporting-query, data-transformation, external-system-orchestration, thin-domain]
|
|
795
|
+
platform_choice:
|
|
796
|
+
source: docs/engineering/backend-platforms.json
|
|
797
|
+
confirms: [platform_profile, spring_boot_version, java_version]
|
|
798
|
+
version_format: exact-patch
|
|
799
|
+
latest_or_range: forbidden
|
|
800
|
+
same_user_decision_as_architecture: true
|
|
785
801
|
recommendation_policy:
|
|
786
802
|
evidence_required: true
|
|
787
803
|
strong_domain_signal_prefers: domain-driven
|
|
@@ -794,7 +810,7 @@ scaffold_architecture_decision:
|
|
|
794
810
|
main_project_has_no_silent_default: true
|
|
795
811
|
child_projects_prefill_parent_default: true
|
|
796
812
|
batch_confirmation_required: true
|
|
797
|
-
prompt_fields: [project, responsibility, agent_recommendation, recommendation_reasons, inherited_from, current_choice, platform_profile, architecture_profile, verification_database, production_database, resolved_modules, warnings]
|
|
813
|
+
prompt_fields: [project, responsibility, agent_recommendation, recommendation_reasons, inherited_from, current_choice, platform_profile, spring_boot_version, java_version, architecture_profile, verification_database, production_database, resolved_modules, warnings]
|
|
798
814
|
missing_or_deferred_action: blocked
|
|
799
815
|
inheritance:
|
|
800
816
|
modes: [root-default, inherit, override]
|
|
@@ -803,9 +819,10 @@ scaffold_architecture_decision:
|
|
|
803
819
|
shared_profile_change_stales_all_affected: true
|
|
804
820
|
new_child_requires_confirmation: true
|
|
805
821
|
persistence:
|
|
806
|
-
required: [decision_id, project_id, parent_project_id, recommended_architecture, recommendation_reasons, confirmed_architecture, override_reason, inheritance_mode, inherited_from, platform_profile, architecture_profile, verification_database, production_database, requested_capabilities, resolved_modules, resolution_version, user_confirmation, decision_inputs_digest, status]
|
|
822
|
+
required: [decision_id, project_id, parent_project_id, recommended_architecture, recommendation_reasons, confirmed_architecture, override_reason, inheritance_mode, inherited_from, platform_profile, exact_spring_boot_version_in_user_snapshot, architecture_profile, verification_database, production_database, requested_capabilities, resolved_modules, resolution_version, user_confirmation, decision_inputs_digest, status]
|
|
807
823
|
downstream_reference: [decision_ref, decision_id, decision_digest]
|
|
808
|
-
|
|
824
|
+
approval_gate: gate.backend-architecture-platform-approved
|
|
825
|
+
existing_repository: reuse-current-registration-without-user-reconfirmation
|
|
809
826
|
change_policy:
|
|
810
827
|
before_lifecycle_approval: update-decision
|
|
811
828
|
after_lifecycle_approval_before_generation: stale-contract-and-recompile
|
|
@@ -41,9 +41,9 @@ Matt phase boundary 是工作阶段之间的上下文决策,不是新的生命
|
|
|
41
41
|
|
|
42
42
|
所有命中项目必须达到 `existing-and-onboarded` 或 `initialized-and-verified`,未命中的交付面必须有带原因的 `not-applicable`。聚合结果、Manifest、验证和 onboarding 证据必须可读且当前;否则 `check.implementation-repositories-ready` 阻断 Ticket 正式化。旧实例恢复时保留已有 Ticket,但将相关 Ticket / Slice Contract 标为 `blocked` / `stale` 并返回本工作单元。
|
|
43
43
|
|
|
44
|
-
`prototype_confirmation` 通过后,先判断实现仓库登记中的 backend `scaffold_status`。当状态为 `required`
|
|
44
|
+
`prototype_confirmation` 通过后,先判断实现仓库登记中的 backend `scaffold_status`。当状态为 `required` 时,在进入 DDD / MVC 分支设计前完成 `gate.backend-architecture-platform-approved`:Agent 按领域复杂度给出 `domain-driven` / `layered-mvc` 推荐和依据,并从 `docs/engineering/backend-platforms.json` 展示可选平台的精确 Spring Boot 补丁版本与 Java 版本;用户在同一次决定中确认架构与平台。本体选择作为子项目预填默认值,用户可批量确认全部项目或逐项覆盖。选择写入 `scaffold-architecture-decisions.yaml`;处于 `undecided`、`recommended`、`awaiting-user-decision` 或 `stale` 时必须阻断,不得默认 DDD、MVC 或 Spring Boot 版本,也不得在生成器内交互。既有工程使用当前 `existing-registration` 的架构及固定工程基线/POM 中的实际 Spring Boot 版本,核验摘要和支持状态后将该门禁记录为 `not-applicable`,不重复询问;架构转换或平台升级另行立项。
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
`gate.backend-architecture-platform-approved` 通过、选择达到 `lifecycle-approved` 且 digest 当前后,才可进入对应的 DDD 战术设计或 MVC 技术设计分支,再完成批准且当前的 Technical Design、Data Architecture Decision v1 和 API Contract Decision v1。数据与 API 均按影响强制:命中则绑定设计及评审闭包,未命中则绑定评估、明确原因和证据。再由 `yss-implementation-contract-compiler` 编译脚手架 schema v4 `controlled-generation` 工作单元合同。顺序为:工程基线与架构/平台推荐 → 用户确认与选择持久化 → DDD / MVC 分支设计 → 技术/数据/API 设计 → 工程合同原子批准 → 脚手架合同持久化 → `domain-driven` 使用 `yss-ddd-scaffold-generator` 或 `layered-mvc` 使用 `yss-layered-mvc-scaffold-generator` → 对应基线/Manifest v4 校验 → 仓库准备 v2 → 实现合同编译器业务合同重编译。`existing` / `initialized` 不重复生成;架构转换或平台升级必须单独立项。schema v3 只允许历史 Manifest 的只读恢复审计,不得新生成。
|
|
47
47
|
|
|
48
48
|
脚手架工作单元必须使用结构化 schema v4 合同 JSON,除工程身份、架构决定、Profile、模块闭包、允许路径和验证命令外,必须以原始字节 digest 绑定 Technical Design、Data Architecture Decision v1、API Contract Decision v1 和 `gate.engineering-contract-approved` 的真实批准记录。API `required` 时 Draft、Validation、独立 Review、Freeze 与工程批准必须绑定同一 OpenAPI YAML 字节;`not-applicable` 时不得携带空占位资产。生成器在创建输出目录前读取并校验所有引用、版本、主体、gate、批准范围、资产绑定与摘要;虚构 URI、字符串自证或仅有 `status: approved` 均无效。三条 Wrapper 命令必须由受控工作单元真实执行并留存证据。非空目标、`--force`、旧项目迁移和模板升级均阻断。脚手架不得生成 Controller、Repository 实现、SQL、领域行为、业务规则、状态机、权限、事务、复杂查询、错误映射、用户可见行为或示例业务 API;`empty-scaffold-verified` 仍不是 `ready-for-agent`。
|
|
49
49
|
|
|
@@ -55,7 +55,7 @@ AND Slice Implementation Contract 已由生命周期编排器批准并持久化
|
|
|
55
55
|
AND Slice Implementation Contract 的 `ticket_ref` 与 `vertical_slice_ticket_ref` 完全一致
|
|
56
56
|
AND 当前工作单元消费的 contract_id/version 与最新批准版本一致
|
|
57
57
|
AND Backend Slice Implementation Contract(后端适用)和 Build Architecture Checklist 已完成
|
|
58
|
-
AND backend 影响且 scaffold_status=required
|
|
58
|
+
AND backend 影响且 scaffold_status=required 时,`gate.backend-architecture-platform-approved` 已由用户同时确认 DDD / MVC 与精确 Spring Boot 版本并达到 lifecycle-approved、统一 schema v4 合同与 Manifest 当前、对应 DDD / Layered MVC 基线、Wrapper 验证和 实现合同编译器重编译均已完成;既有工程只核验并复用当前登记值
|
|
59
59
|
AND frontend 影响且无已有工程时,统一 schema v4 Project Scaffold Contract 已批准、持久化且当前,模板 bundled manifest 摘要或 Git commit 已锁定,`pnpm install --frozen-lockfile` 与工程基线要求的 lint/type-check/build 已实际通过
|
|
60
60
|
AND 所有后续生成代码均绑定主 YSS skill、依赖闭包、允许写路径、预期证据和 YSS Skill Execution Result
|
|
61
61
|
AND UI 影响切片的前端实现还原计划已通过 schema 校验、`template=false`、`status=approved`,且基线引用可读取
|
|
@@ -71,6 +71,6 @@ finding 分为 `requirement-violation/missing-evidence/important-risk/suggestion
|
|
|
71
71
|
|
|
72
72
|
实施就绪和派发必须同时提供 `user_decisions`、`slice_contract_ref` 与 `vertical_slice_ticket_ref`。Worker 任务包通过 `user_decisions` 传递记录,不能只声明 `ready_for_agent=true`。
|
|
73
73
|
|
|
74
|
-
脚手架 `user_confirmation`
|
|
74
|
+
脚手架 `user_confirmation` 使用 `gate.backend-architecture-platform-approved`,`user_decision_ref/decision_subject_ref` 的主体为分支设计前的决策输入快照;当前范围至少包含项目 ID、确认的架构、平台 Profile、精确 Spring Boot 补丁版本、Java 版本和 `decision_inputs_digest`。先获得真实回复,门禁通过后才能进入 DDD 战术设计或 MVC 技术设计,再由生命周期批准生成合同;不能回到设计 skill 或生成器内提问。既有工程核验并复用当前登记值,该门禁记录为 `not-applicable`;升级或架构转换不得冒充复用。
|
|
75
75
|
|
|
76
76
|
Git commit/push、外部动作仍分别检查已有授权和其范围。用户对一个具体动作的明确自然语言授权可整理成结构化记录,不必再次要求填写内部字段;生命周期批准不隐含其他动作授权。
|
|
@@ -50,7 +50,7 @@ Plan 的目标与退出条件由 `docs/process/lifecycle-registry.yaml` 持有
|
|
|
50
50
|
- 业务边界与规则设计是本类事实的权威资产,方案决策包只通过内部字段 `domain_strategy_ref` 引用它。两个合同的 `context_snapshot.context_ref` 必须精确为仓库根 `CONTEXT.md`,禁止子目录、`CONTEXT-MAP.md`、绝对路径和 Markdown 伪锚点。
|
|
51
51
|
- 进入 `check.domain-strategy-approved` 或 `check.stage-decision-package-approved` 的外部决策证据必须引用通过校验的 `yss-research` `evidence-audited` 研究包;研究包只提供证据,不得直接修改本技能资产或批准门禁。
|
|
52
52
|
- `stage_decision_package` 必须经过 `draft → ready-for-human → approved`;起草者不得自签。
|
|
53
|
-
- 内部专业审查为 `check.domain-strategy-approved` 和 `check.stage-decision-package-approved`,汇入 `gate.plan-approved` 一次确认,实际状态由 `yss-product-lifecycle`
|
|
53
|
+
- 内部专业审查为 `check.domain-strategy-approved` 和 `check.stage-decision-package-approved`,汇入 `gate.plan-approved` 一次确认,实际状态由 `yss-product-lifecycle` 维护。新 Plan 流程由产品经理在一个 `review-bundle.plan` 任务中逐项给出结论,并以相同 `review_session_id` 汇总到 Plan 门禁;未命中项只记录有依据的 `not-applicable`。资产的 `approval_ref` 可指向该 bundle 中自己的唯一结论;验证器按 check ID 选择,旧单条批准继续兼容。
|
|
54
54
|
- 下游只能消费批准且版本当前的包;发现语义冲突返回 `drift` / `new_impacts`,不得静默修改上游。
|
|
55
55
|
|
|
56
56
|
## 结果合同
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
- `concept_candidates`、`invariants`、`context_snapshot`;
|
|
11
11
|
- `downstream_mapping`、`evidence_refs`、`approval`。
|
|
12
12
|
|
|
13
|
+
`approval.approval_ref` 可以指向 `check.domain-strategy-approved` 单条记录,或指向包含该唯一结论的 `review-bundle.plan`;验证器按 check ID 选择结论并核对 `approval.approver`。bundle 中另一项检查的结论不能替代本检查。
|
|
14
|
+
|
|
13
15
|
## 业务责任区
|
|
14
16
|
|
|
15
17
|
每个业务责任区声明内部 `context_id`、职责边界、非职责、业务板块分类、责任人、关键场景和本地词汇引用。`context_id` 是稳定身份,由 Agent 维护;不得使用代码模块、数据库 schema 或菜单路径替代。
|
package/template/.cursor/skills/yss-stage-decision/references/stage-decision-package-contract.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
- `context_snapshot`:只引用根 `CONTEXT.md`,并绑定结构化术语身份、全文摘要和引用集摘要;
|
|
10
10
|
- `domain_strategy_ref`:领域战略合同的稳定 ID、版本、digest 和批准状态;
|
|
11
11
|
- UI/API/Data/Backend/Frontend/跨仓/高风险影响面布尔值;
|
|
12
|
-
- 每个消费者能力的稳定 `mapping_id`、领域来源 ID
|
|
12
|
+
- 每个消费者能力的稳定 `mapping_id`、领域来源 ID、传播方式、重新批准条件、证据引用和审查记录。`approval.approval_ref` 必须指向可读取的 `check.stage-decision-package-approved` 单条审查记录,或指向包含该唯一结论的 `review-bundle.plan`;验证器按 check ID 选择并校验,`approval.approver` 必须与选中结论中的 `role_id` 一致。该检查结论汇入 `gate.plan-approved`,不单独暂停用户。
|
|
13
13
|
|
|
14
14
|
## 未决项规则
|
|
15
15
|
|
|
@@ -3,7 +3,7 @@ import { readFile } from "node:fs/promises";
|
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { parseArgs } from "node:util";
|
|
5
5
|
import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
|
|
6
|
-
import { loadApprovalRecord, resolveApprovalRef,
|
|
6
|
+
import { loadApprovalRecord, resolveApprovalRef, validateApprovalRecord } from "../../../../scripts/lib/approval-record.mjs";
|
|
7
7
|
import { verifyContextSnapshot } from "../../../../scripts/lib/context-contract.mjs";
|
|
8
8
|
|
|
9
9
|
import { extractTraceability } from "../../../../scripts/lib/strategic-handoff-rules.mjs";
|
|
@@ -196,8 +196,8 @@ function validate(data, contextRoot) {
|
|
|
196
196
|
if (approval.current_version !== data.domain_version) errors.push("approval.current_version 必须等于 domain_version");
|
|
197
197
|
try {
|
|
198
198
|
const approvalPath = resolveApprovalRef(approval.approval_ref);
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
const record = loadApprovalRecord(approvalPath, "check.domain-strategy-approved");
|
|
200
|
+
validateApprovalRecord(record, { requireApproved: true });
|
|
201
201
|
if (record.gate_id !== "check.domain-strategy-approved") errors.push("approval.approval_ref 的 gate_id 必须为 check.domain-strategy-approved");
|
|
202
202
|
if (record.role_id !== approval.approver) errors.push("approval.approver 必须与会签记录 role_id 一致");
|
|
203
203
|
} catch (error) { errors.push(`approval.approval_ref 会签记录无效: ${error.message}`); }
|
package/template/.cursor/skills/yss-stage-decision/scripts/validate-stage-decision-package.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { resolve } from "node:path";
|
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
7
7
|
import { parseDocument } from "../../../../scripts/vendor/yaml.mjs";
|
|
8
|
-
import { loadApprovalRecord, resolveApprovalRef,
|
|
8
|
+
import { loadApprovalRecord, resolveApprovalRef, validateApprovalRecord } from "../../../../scripts/lib/approval-record.mjs";
|
|
9
9
|
import { verifyContextSnapshot } from "../../../../scripts/lib/context-contract.mjs";
|
|
10
10
|
|
|
11
11
|
const required = ["schema_version", "stage_decision_id", "package_version", "status", "problem_statement", "target_users", "mvp", "non_goals", "success_criteria", "test_seams", "confirmed_decisions", "assumptions", "constraints", "unresolved_items", "context_snapshot", "domain_strategy_ref", "impact_assessment", "downstream_mapping", "evidence_refs", "approval"];
|
|
@@ -129,8 +129,8 @@ async function validate(data, contextRoot) {
|
|
|
129
129
|
if (data.status === "approved" && nonEmpty(approval.approval_ref)) {
|
|
130
130
|
try {
|
|
131
131
|
const approvalPath = resolveApprovalRef(approval.approval_ref);
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
const record = loadApprovalRecord(approvalPath, "check.stage-decision-package-approved");
|
|
133
|
+
validateApprovalRecord(record, { requireApproved: true });
|
|
134
134
|
if (record.gate_id !== "check.stage-decision-package-approved") errors.push("approval_ref 的 gate_id 必须为 check.stage-decision-package-approved");
|
|
135
135
|
if (record.role_id !== approval.approver) errors.push("approval.approver 必须与会签记录 role_id 一致");
|
|
136
136
|
} catch (error) { errors.push(`approval_ref 会签记录无效: ${error.message}`); }
|
|
@@ -201,6 +201,39 @@ try {
|
|
|
201
201
|
const packagePass = run(packageValidator, packageFile, temporaryRoot);
|
|
202
202
|
if (packagePass.status !== 0) throw new Error(`valid v3 stage decision package should pass: ${packagePass.stderr}`);
|
|
203
203
|
|
|
204
|
+
const bundleFile = join(temporaryRoot, "plan-review-bundle.json");
|
|
205
|
+
const bundledDomainValue = parseYaml(domainSource);
|
|
206
|
+
bundledDomainValue.approval.approval_ref = bundleFile;
|
|
207
|
+
const bundledDomainSource = JSON.stringify(bundledDomainValue, null, 2);
|
|
208
|
+
const bundledDomainFile = join(temporaryRoot, "domain-strategy-bundled.yaml");
|
|
209
|
+
await writeFile(bundledDomainFile, bundledDomainSource);
|
|
210
|
+
const bundledPackageValue = parseYaml(packageSource);
|
|
211
|
+
bundledPackageValue.domain_strategy_ref.persisted_ref = "domain-strategy-bundled.yaml";
|
|
212
|
+
bundledPackageValue.domain_strategy_ref.digest = digestYaml(bundledDomainSource);
|
|
213
|
+
bundledPackageValue.approval.approval_ref = bundleFile;
|
|
214
|
+
const bundledPackageSource = JSON.stringify(bundledPackageValue, null, 2);
|
|
215
|
+
const bundledPackageFile = join(temporaryRoot, "stage-decision-bundled.yaml");
|
|
216
|
+
await writeFile(bundledPackageFile, bundledPackageSource);
|
|
217
|
+
await writeFile(bundleFile, JSON.stringify({
|
|
218
|
+
schema_version: 1,
|
|
219
|
+
kind: "review-bundle",
|
|
220
|
+
bundle_id: "review-bundle.plan",
|
|
221
|
+
task_id: "task.plan-review.supplier-admission",
|
|
222
|
+
work_unit_id: "work-unit.plan-requirements",
|
|
223
|
+
review_session_id: "review-session.plan.supplier-admission",
|
|
224
|
+
role_id: "role.product-manager",
|
|
225
|
+
runtime_id: "runtime.generic",
|
|
226
|
+
principal_ref: "instance:role.product-manager",
|
|
227
|
+
reviews: [
|
|
228
|
+
{ schema_version: 1, gate_id: "check.domain-strategy-approved", decision: "approved", actor_kind: "digital-human", role_id: "role.product-manager", runtime_id: "runtime.generic", principal_ref: "instance:role.product-manager", drafter_role_id: "role.requirements-manager", drafter_principal_ref: "instance:role.requirements-manager", subject_ref: bundledDomainFile, subject_digest: digestYaml(bundledDomainSource).slice(7), approval_scope: ["feature.supplier-admission"], evidence_refs: [bundledDomainFile] },
|
|
229
|
+
{ schema_version: 1, gate_id: "check.stage-decision-package-approved", decision: "approved", actor_kind: "digital-human", role_id: "role.product-manager", runtime_id: "runtime.generic", principal_ref: "instance:role.product-manager", drafter_role_id: "role.requirements-manager", drafter_principal_ref: "instance:role.requirements-manager", subject_ref: bundledPackageFile, subject_digest: digestYaml(bundledPackageSource).slice(7), approval_scope: ["feature.supplier-admission"], evidence_refs: [bundledPackageFile] }
|
|
230
|
+
]
|
|
231
|
+
}, null, 2));
|
|
232
|
+
const bundledDomainPass = run(validator, bundledDomainFile, temporaryRoot);
|
|
233
|
+
if (bundledDomainPass.status !== 0) throw new Error(`domain strategy should select its conclusion from Plan review-bundle: ${bundledDomainPass.stderr}`);
|
|
234
|
+
const bundledPackagePass = run(packageValidator, bundledPackageFile, temporaryRoot);
|
|
235
|
+
if (bundledPackagePass.status !== 0) throw new Error(`stage decision should select its conclusion from Plan review-bundle: ${bundledPackagePass.stderr}`);
|
|
236
|
+
|
|
204
237
|
const v2Stage = toV2Stage(packageSource, digestYaml(v2DomainSource));
|
|
205
238
|
const v2StageFile = join(temporaryRoot, "stage-decision-v2.yaml");
|
|
206
239
|
await writeFile(v2StageFile, JSON.stringify(v2Stage, null, 2));
|
|
@@ -9,7 +9,7 @@ description: 在 YSS 技术分析阶段将批准的战略领域输入细化为
|
|
|
9
9
|
|
|
10
10
|
## 适用边界
|
|
11
11
|
|
|
12
|
-
- 由 `yss-technical-design` 在已确认 `domain-driven`
|
|
12
|
+
- 由 `yss-technical-design` 在已确认 `domain-driven` 的技术设计分支中调用;新建后端必须先通过 `gate.backend-architecture-platform-approved`,由用户在同一次决定中确认 DDD / MVC 与精确 Spring Boot 版本。传统 MVC 使用 `yss-mvc-design`;既有工程直接核验并复用当前登记架构及固定工程基线/POM 中的实际 Spring Boot 版本,不重复询问。不得按状态、一致性影响、目录或默认值单独推断为 DDD。
|
|
13
13
|
- 输入必须是版本当前的 Spec、功能架构、战略 DDD、状态矩阵、OpenAPI Draft / Freeze、ADR 和工程约束。若输入来自 Strategic Design Handoff,必须先用 `scripts/verify-strategic-context-import` 验证历史 v3/v4 或当前 v5 的 `source_context_snapshot` / `context_delta` 已对账到目标仓根 `CONTEXT.md`,对应的 prototype 或 existing UI baseline 可读取且摘要当前,并且目标侧 `context_reconciliation` 有效;未完成时不得开始战术建模。
|
|
14
14
|
- 默认将结果写入系统概要设计 / 数据架构中的 Tactical DDD Check;聚合、状态机、一致性或持久化映射复杂到无法清楚表达时,才升级为独立战术设计文档。
|
|
15
15
|
- 没有聚合、状态、不变量、一致性或领域边界影响时返回 `not-applicable` 及原因,不生成空设计。
|
|
@@ -17,7 +17,7 @@ description: 在 YSS 技术分析中统一承接需求与战略输入,按已
|
|
|
17
17
|
|
|
18
18
|
先读根 `CONTEXT.md`、已批准且当前的 Spec、业务规则、关键场景、适用的 API 契约、ADR 和工程约束。没有 API 或其他专项影响时记录有依据的不适用,不生成占位设计。
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
按项目绑定架构选择的来源及摘要。新工程必须先通过 `gate.backend-architecture-platform-approved`:Agent 展示 DDD / MVC 推荐依据及平台清单中的精确 Spring Boot、Java 版本,用户在同一次决定中确认两项内容;决定持久化到 `scaffold-architecture-decisions.yaml`,再进入对应分支,后续脚手架消费同一决定。既有工程核验并沿用当前登记架构及固定工程基线/POM 中的实际 Spring Boot 版本,该门禁记录为 `not-applicable`,不重复询问;架构转换或平台升级另行立项。只有 `domain-driven` 和 `layered-mvc` 两种架构族,不能从目录推断或默认 DDD、MVC 或 Spring Boot 版本。具体 Profile 及模块边界消费技能注册表与 `docs/agents/backend-architecture-profiles.md`。
|
|
21
21
|
|
|
22
22
|
- `domain-driven`:调用 `yss-tactical-design`,补齐适用的战略领域输入。
|
|
23
23
|
- `layered-mvc`:调用 `yss-mvc-design`,不要求战略 DDD、聚合、值对象、Domain Event 或 DDD Gateway。
|
package/template/.cursor/skills/yss-technical-design/references/technical-design-contract.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
## 共同头
|
|
6
6
|
|
|
7
7
|
- `schema_version: 2`、`technical_design_id: technical-design.<name>`、`version: vN`、`status`、`context_ref: CONTEXT.md`。
|
|
8
|
-
- `architecture`:`family`、`project_id`、`source_kind: scaffold-decision | existing-registration`、`decision_ref`、`decision_digest`。新项目引用正式且 current
|
|
8
|
+
- `architecture`:`family`、`project_id`、`source_kind: scaffold-decision | existing-registration`、`decision_ref`、`decision_digest`。新项目引用正式且 current 的脚手架决定,所选项目必须已通过 `gate.backend-architecture-platform-approved`,用户决定同时绑定 DDD / MVC、平台 Profile、精确 Spring Boot 与 Java 版本;既有登记引用当前 `project_id` 和 `architecture_identity.architecture_family`,并从固定工程基线/POM 复用实际 Spring Boot 版本,不重新询问。架构或平台来源变化须重新绑定和审查,不能改合同字段冒充用户改选或升级。
|
|
9
9
|
- `inputs`:每行 `{kind, ref, version, digest}`,kind 为 context/spec/rules/scenarios/api/adr/engineering/strategic;至少包含根 CONTEXT.md 与 Spec。适用的工程/API 约束同样绑定。无 API 影响理由记录在需求或工程输入中。DDD 另须 strategic 输入,MVC 不要求。
|
|
10
10
|
- `source_items`:无战略包时从批准需求提取稳定规则和场景 `{source_id, kind: rule | scenario, critical, source_ref}`。source_ref 必须对应 inputs,不复制源正文成为第二事实源。
|
|
11
11
|
- `traceability`:逐项对应 source_items。沿用 `tactical_refs` 字段名以兼容承接协议,其值在新合同中可指向 MVC 用例、规则或 DDD 对象;其他字段与战略承接 rows 相同。implemented 仅表示设计承接已落实,不表示代码已实现。
|
|
@@ -56,7 +56,7 @@ try {
|
|
|
56
56
|
ddd.design.aggregate_catalog[0].api_exposure = 'public'; ddd.digest = technicalDigest(ddd);
|
|
57
57
|
await assert.rejects(() => validate(ddd), /internal-only/); checks++;
|
|
58
58
|
const scaffold = mvcFixture(root);
|
|
59
|
-
const decision = attachScaffoldDecisionFixture(path.join(root, 'decision-evidence'), { project_id: 'example', status: 'user-confirmed', confirmed_architecture: 'layered-mvc', decision_inputs_digest: `sha256:${'1'.repeat(64)}`, user_confirmation: { confirmation_ref: 'user-message', confirmed_by: 'user' } });
|
|
59
|
+
const decision = attachScaffoldDecisionFixture(path.join(root, 'decision-evidence'), { project_id: 'example', status: 'user-confirmed', confirmed_architecture: 'layered-mvc', platform_profile: 'spring-boot-2.7-jdk8', decision_inputs_digest: `sha256:${'1'.repeat(64)}`, user_confirmation: { confirmation_ref: 'user-message', confirmed_by: 'user' } });
|
|
60
60
|
const record = { status: 'current', template: false, decisions: [decision] };
|
|
61
61
|
const recordFile = path.join(root, 'decision.json');
|
|
62
62
|
writeFileSync(recordFile, JSON.stringify(record));
|
|
@@ -23,7 +23,7 @@ description: 用于生成完整的 YSS DDD 多模块后端脚手架。当用户
|
|
|
23
23
|
|
|
24
24
|
## Spring Boot / Java 平台选择
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
调用本技能前由生命周期编排器展示 `scripts/backend-platforms` 的精确版本清单及兼容状态,并通过 `gate.backend-architecture-platform-approved` 把架构、Spring Boot、Java 和 YSS 父 POM/BOM 合并展示、取得真实用户确认;生成器不提问、不猜版本、不使用 `x` 或 `latest`。已有批准且当前的选择展示摘要后复用;既有工程核验并复用登记值,不触发该门禁。
|
|
27
27
|
|
|
28
28
|
- 候选平台:Boot 2.7.18 / Java 8,Boot 3.5.16 / Java 17 或 21,Boot 4.1.1 / Java 17 或 21。新 Boot 默认推荐 Java 17;候选不等于可生成。
|
|
29
29
|
- 独立子项目可继承主项目组合或覆盖,必须逐项目确认(允许一次确认明确列出的项目);同一 Maven Reactor 使用一个平台。
|
|
@@ -36,7 +36,7 @@ description: 用于生成完整的 YSS DDD 多模块后端脚手架。当用户
|
|
|
36
36
|
|
|
37
37
|
## 优先流程
|
|
38
38
|
|
|
39
|
-
1. 确认服务级 `scaffold_request_id
|
|
39
|
+
1. 确认服务级 `scaffold_request_id`、已通过 `gate.backend-architecture-platform-approved` 的 `domain-driven` 架构与精确 Spring Boot 版本选择及 digest、项目名、基础包名、Maven 项目坐标、父 POM GAV、YSS Components BOM 版本、输出目录和批准 Profile。Java `base_package` 与 Maven `group_id` 是两个独立输入,不得相互推导;脚手架发生在 Ticket 正式化前,不使用 `slice_id` 伪造切片身份。
|
|
40
40
|
Harness 内输出目录必须是 `apps/backend/` 容器,生成器再以 `project_name` 创建 `apps/backend/<project>/`;禁止使用 `app/backend/`、`app/frontend/` 或把 `apps/backend/` 之外的容器根当作后端项目根。
|
|
41
41
|
2. 优先运行 `node scripts/generate_and_verify_scaffold.mjs`,在同一个受控工作流中生成骨架并执行真实 Maven 验证。`generate_scaffold.mjs` 只是底层生成原语,单独返回 0 不代表脚手架完成。
|
|
42
42
|
3. 检查生成的模块名、POM、机械启动入口、基础配置文件和包路径。
|
|
@@ -47,7 +47,7 @@ description: "编译或重验 YSS Slice Implementation Contract、最小 Skill
|
|
|
47
47
|
- Harness 内实现路径必须落在 `apps/backend/<project>/` 或 `apps/frontend/<project>/` 的具体项目目录;`apps/backend/`、`apps/frontend/` 只能作为容器,`app/backend/`、`app/frontend/` 及其子路径一律阻断。外部实现仓库使用其登记的真实项目根路径。`git-submodule` 使用 `implementation_path_policy: git-submodule-harness-apps`,空 gitlink、detached HEAD 或 `--force` 覆盖挂载点不得脚手架;`inspectWorkingTreeScope.writable` 必须为显式布尔值。
|
|
48
48
|
- 当前用户、缓存、审计、Excel、分布式 ID、请求校验、错误映射、加解密或网关韧性命中时,必须按 `compiler-contract.yaml` 的 `impact_to_capabilities` 补齐入口 capability;不能只在 `boundaries.md` 中提及。仅复用已经验证的平台认证 / 授权能力不算 component impact,不自动增加权限专项 skill。
|
|
49
49
|
- 业务行为使用 `behavior-tdd`;只有机械脚手架/生成物可用 `controlled-generation`,并记录例外和验证。
|
|
50
|
-
- 阶段 5 若命中交付面且无已有工程,按 Project Scaffold Contract schema v4 编译 `controlled-generation` 合同 draft
|
|
50
|
+
- 阶段 5 若命中交付面且无已有工程,按 Project Scaffold Contract schema v4 编译 `controlled-generation` 合同 draft。后端先读取已通过 `gate.backend-architecture-platform-approved` 的架构与精确 Spring Boot 版本决定,并以原始字节 digest 绑定批准且当前的 Technical Design、Data Architecture Decision v1、API Contract Decision v1 及 `gate.engineering-contract-approved` 真实批准记录;编译器不得自行默认、提问或批准。既有工程核验并复用当前登记架构及固定工程基线/POM 中的实际版本,不重新询问或生成。API `required` 时工程批准还必须直接绑定冻结 OpenAPI YAML 的版本与摘要,`not-applicable` 时必须有影响评估、明确原因和证据。前端绑定标准模板精确 commit、应用标识、路由、OpenAPI 影响、目标路径和 `init_git` 决定。合同经生命周期批准并持久化后才能运行生成器。历史后端 schema v3 只允许 Manifest 只读恢复审计,并须补齐 API 对账,不得新生成;前端只接受 v4。生成与验证完成、仓库登记并通过 `check.implementation-repositories-ready` 后,才编译 Ticket 与业务 Slice Contract。
|
|
51
51
|
- 脚手架合同在编译阶段只能是 `draft` / `ready-for-lifecycle-review` / `blocked`;只有生命周期编排器可以把已持久化脚手架合同标记为 `approved`。脚手架合同只覆盖业务代码前的工程骨架工作单元;生成、基线校验和合同重编译完成后,它不能替代脚手架后的 Slice Implementation Contract。
|
|
52
52
|
- 脚手架输出消费批准的脚手架合同;脚手架后的所有生成后端代码都必须绑定当前批准且版本当前的 Slice Implementation Contract、主 YSS skill、依赖闭包、允许写路径、预期证据和 YSS Skill Execution Result。打印命令、`./mvnw validate` 单项通过或脚手架成功不能替代合同批准;生成范围从机械内容变成业务行为时触发完整重路由。
|
|
53
53
|
- 专项结果中的越界路径、缺失证据、`drift`、`violation` 或 `new_impacts` 必须阻断或重路由。
|
|
@@ -18,7 +18,7 @@ description: 用于在生命周期已批准的脚手架合同下生成按批准
|
|
|
18
18
|
|
|
19
19
|
## Spring Boot / Java 平台选择
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
调用本技能前由生命周期编排器展示 `scripts/backend-platforms` 的精确版本清单及兼容状态,并通过 `gate.backend-architecture-platform-approved` 把架构、Spring Boot、Java 和 YSS 父 POM/BOM 合并展示、取得真实用户确认;生成器不提问、不猜版本、不使用 `x` 或 `latest`。已有批准且当前的选择展示摘要后复用;既有工程核验并复用登记值,不触发该门禁。
|
|
22
22
|
|
|
23
23
|
- 候选平台:Boot 2.7.18 / Java 8,Boot 3.5.16 / Java 17 或 21,Boot 4.1.1 / Java 17 或 21。新 Boot 默认推荐 Java 17;候选不等于可生成。
|
|
24
24
|
- 独立子项目可继承主项目组合或覆盖,必须逐项目确认(允许一次确认明确列出的项目);同一 Maven Reactor 使用一个平台。
|
|
@@ -382,7 +382,15 @@ work_unit_routes:
|
|
|
382
382
|
technical_design:
|
|
383
383
|
applies_when: backend_delivery_impact
|
|
384
384
|
new_backend_repository: required
|
|
385
|
-
architecture_source:
|
|
385
|
+
architecture_source: new-project-user-gate-or-current-existing-registration-before-branch-design
|
|
386
|
+
pre_design_gate:
|
|
387
|
+
id: gate.backend-architecture-platform-approved
|
|
388
|
+
applies_when: new_backend_repository
|
|
389
|
+
confirms: [architecture_family, exact_spring_boot_version]
|
|
390
|
+
architecture_choices: [domain-driven, layered-mvc]
|
|
391
|
+
platform_source: docs/engineering/backend-platforms.json
|
|
392
|
+
existing_repository: not-applicable-reuse-current-registration
|
|
393
|
+
missing_or_stale: blocked
|
|
386
394
|
branches:
|
|
387
395
|
domain-driven: yss-tactical-design
|
|
388
396
|
layered-mvc: yss-mvc-design
|
|
@@ -414,6 +422,7 @@ work_unit_routes:
|
|
|
414
422
|
placeholder_assets: forbidden
|
|
415
423
|
atomic_approval_gate: gate.engineering-contract-approved
|
|
416
424
|
human_gate: gate.engineering-contract-approved
|
|
425
|
+
entry_user_gate: gate.backend-architecture-platform-approved
|
|
417
426
|
applies_when: technical_or_contract_impact
|
|
418
427
|
not_applicable_reason: no_technical_or_contract_impact
|
|
419
428
|
work-unit.implementation-repository-preparation:
|
|
@@ -771,7 +780,8 @@ scaffold_architecture_decision:
|
|
|
771
780
|
applies_when: [backend_impact, scaffold_status_required]
|
|
772
781
|
owner: yss-product-lifecycle
|
|
773
782
|
stage: work-unit.technical-analysis
|
|
774
|
-
|
|
783
|
+
gate: gate.backend-architecture-platform-approved
|
|
784
|
+
timing: after-impact-and-platform-candidate-resolution-before-ddd-or-mvc-branch-design
|
|
775
785
|
source: scaffold-architecture-decisions.yaml
|
|
776
786
|
schema_version: 1
|
|
777
787
|
statuses: [undecided, recommended, awaiting-user-decision, user-confirmed, lifecycle-approved, consumed, stale]
|
|
@@ -782,6 +792,12 @@ scaffold_architecture_decision:
|
|
|
782
792
|
layered-mvc:
|
|
783
793
|
display_name: MVC 开发脚手架
|
|
784
794
|
recommendation_signals: [crud, reporting-query, data-transformation, external-system-orchestration, thin-domain]
|
|
795
|
+
platform_choice:
|
|
796
|
+
source: docs/engineering/backend-platforms.json
|
|
797
|
+
confirms: [platform_profile, spring_boot_version, java_version]
|
|
798
|
+
version_format: exact-patch
|
|
799
|
+
latest_or_range: forbidden
|
|
800
|
+
same_user_decision_as_architecture: true
|
|
785
801
|
recommendation_policy:
|
|
786
802
|
evidence_required: true
|
|
787
803
|
strong_domain_signal_prefers: domain-driven
|
|
@@ -794,7 +810,7 @@ scaffold_architecture_decision:
|
|
|
794
810
|
main_project_has_no_silent_default: true
|
|
795
811
|
child_projects_prefill_parent_default: true
|
|
796
812
|
batch_confirmation_required: true
|
|
797
|
-
prompt_fields: [project, responsibility, agent_recommendation, recommendation_reasons, inherited_from, current_choice, platform_profile, architecture_profile, verification_database, production_database, resolved_modules, warnings]
|
|
813
|
+
prompt_fields: [project, responsibility, agent_recommendation, recommendation_reasons, inherited_from, current_choice, platform_profile, spring_boot_version, java_version, architecture_profile, verification_database, production_database, resolved_modules, warnings]
|
|
798
814
|
missing_or_deferred_action: blocked
|
|
799
815
|
inheritance:
|
|
800
816
|
modes: [root-default, inherit, override]
|
|
@@ -803,9 +819,10 @@ scaffold_architecture_decision:
|
|
|
803
819
|
shared_profile_change_stales_all_affected: true
|
|
804
820
|
new_child_requires_confirmation: true
|
|
805
821
|
persistence:
|
|
806
|
-
required: [decision_id, project_id, parent_project_id, recommended_architecture, recommendation_reasons, confirmed_architecture, override_reason, inheritance_mode, inherited_from, platform_profile, architecture_profile, verification_database, production_database, requested_capabilities, resolved_modules, resolution_version, user_confirmation, decision_inputs_digest, status]
|
|
822
|
+
required: [decision_id, project_id, parent_project_id, recommended_architecture, recommendation_reasons, confirmed_architecture, override_reason, inheritance_mode, inherited_from, platform_profile, exact_spring_boot_version_in_user_snapshot, architecture_profile, verification_database, production_database, requested_capabilities, resolved_modules, resolution_version, user_confirmation, decision_inputs_digest, status]
|
|
807
823
|
downstream_reference: [decision_ref, decision_id, decision_digest]
|
|
808
|
-
|
|
824
|
+
approval_gate: gate.backend-architecture-platform-approved
|
|
825
|
+
existing_repository: reuse-current-registration-without-user-reconfirmation
|
|
809
826
|
change_policy:
|
|
810
827
|
before_lifecycle_approval: update-decision
|
|
811
828
|
after_lifecycle_approval_before_generation: stale-contract-and-recompile
|