create-yss-spec 3.3.7 → 3.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +12 -13
  2. package/package.json +1 -1
  3. package/template/.agents/skills/.strategic-design-skills-manifest.json +2 -2
  4. package/template/.agents/skills/implementation-repo-onboarding/SKILL.md +2 -2
  5. package/template/.agents/skills/yss-application/SKILL.md +1 -1
  6. package/template/.agents/skills/yss-application/references/profiles/existing-domain-driven-maven.md +5 -0
  7. package/template/.agents/skills/yss-application/references/profiles/existing-layered-mvc-maven.md +5 -0
  8. package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -2
  9. package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +4 -0
  10. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +6 -1
  11. package/template/.agents/skills/yss-prototype-stage/SKILL.md +10 -1
  12. package/template/.agents/skills/yss-technical-design/SKILL.md +2 -0
  13. package/template/.agents/skills/yss-technical-design/references/engineering-design.schema.json +224 -0
  14. package/template/.agents/skills/yss-technical-design/references/technical-design-common.schema.json +6 -0
  15. package/template/.agents/skills/yss-technical-design/references/technical-design.schema.json +288 -10
  16. package/template/.agents/skills/yss-technical-design/scripts/engineering-design.mjs +30 -0
  17. package/template/.agents/skills/yss-technical-design/scripts/generate-schema.mjs +2 -1
  18. package/template/.agents/skills/yss-technical-design/scripts/validate-technical-design.mjs +20 -8
  19. package/template/.agents/skills/yss-technical-design/tests/engineering-scenarios.mjs +12 -0
  20. package/template/.agents/skills/yss-web-controller/SKILL.md +1 -1
  21. package/template/.agents/skills/yss-web-controller/references/profiles/existing-domain-driven-maven.md +5 -0
  22. package/template/.agents/skills/yss-web-controller/references/profiles/existing-layered-mvc-maven.md +5 -0
  23. package/template/.codex/skills/implementation-repo-onboarding/SKILL.md +2 -2
  24. package/template/.codex/skills/yss-application/SKILL.md +1 -1
  25. package/template/.codex/skills/yss-application/references/profiles/existing-domain-driven-maven.md +5 -0
  26. package/template/.codex/skills/yss-application/references/profiles/existing-layered-mvc-maven.md +5 -0
  27. package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -2
  28. package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +4 -0
  29. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +6 -1
  30. package/template/.codex/skills/yss-prototype-stage/SKILL.md +10 -1
  31. package/template/.codex/skills/yss-technical-design/SKILL.md +2 -0
  32. package/template/.codex/skills/yss-technical-design/references/engineering-design.schema.json +224 -0
  33. package/template/.codex/skills/yss-technical-design/references/technical-design-common.schema.json +6 -0
  34. package/template/.codex/skills/yss-technical-design/references/technical-design.schema.json +288 -10
  35. package/template/.codex/skills/yss-technical-design/scripts/engineering-design.mjs +30 -0
  36. package/template/.codex/skills/yss-technical-design/scripts/generate-schema.mjs +2 -1
  37. package/template/.codex/skills/yss-technical-design/scripts/validate-technical-design.mjs +20 -8
  38. package/template/.codex/skills/yss-technical-design/tests/engineering-scenarios.mjs +12 -0
  39. package/template/.codex/skills/yss-web-controller/SKILL.md +1 -1
  40. package/template/.codex/skills/yss-web-controller/references/profiles/existing-domain-driven-maven.md +5 -0
  41. package/template/.codex/skills/yss-web-controller/references/profiles/existing-layered-mvc-maven.md +5 -0
  42. package/template/.cursor/skills/implementation-repo-onboarding/SKILL.md +2 -2
  43. package/template/.cursor/skills/yss-application/SKILL.md +1 -1
  44. package/template/.cursor/skills/yss-application/references/profiles/existing-domain-driven-maven.md +5 -0
  45. package/template/.cursor/skills/yss-application/references/profiles/existing-layered-mvc-maven.md +5 -0
  46. package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -2
  47. package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +4 -0
  48. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +6 -1
  49. package/template/.cursor/skills/yss-prototype-stage/SKILL.md +10 -1
  50. package/template/.cursor/skills/yss-technical-design/SKILL.md +2 -0
  51. package/template/.cursor/skills/yss-technical-design/references/engineering-design.schema.json +224 -0
  52. package/template/.cursor/skills/yss-technical-design/references/technical-design-common.schema.json +6 -0
  53. package/template/.cursor/skills/yss-technical-design/references/technical-design.schema.json +288 -10
  54. package/template/.cursor/skills/yss-technical-design/scripts/engineering-design.mjs +30 -0
  55. package/template/.cursor/skills/yss-technical-design/scripts/generate-schema.mjs +2 -1
  56. package/template/.cursor/skills/yss-technical-design/scripts/validate-technical-design.mjs +20 -8
  57. package/template/.cursor/skills/yss-technical-design/tests/engineering-scenarios.mjs +12 -0
  58. package/template/.cursor/skills/yss-web-controller/SKILL.md +1 -1
  59. package/template/.cursor/skills/yss-web-controller/references/profiles/existing-domain-driven-maven.md +5 -0
  60. package/template/.cursor/skills/yss-web-controller/references/profiles/existing-layered-mvc-maven.md +5 -0
  61. package/template/.pi/skills/implementation-repo-onboarding/SKILL.md +2 -2
  62. package/template/.pi/skills/yss-application/SKILL.md +1 -1
  63. package/template/.pi/skills/yss-application/references/profiles/existing-domain-driven-maven.md +5 -0
  64. package/template/.pi/skills/yss-application/references/profiles/existing-layered-mvc-maven.md +5 -0
  65. package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -2
  66. package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +4 -0
  67. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +6 -1
  68. package/template/.pi/skills/yss-prototype-stage/SKILL.md +10 -1
  69. package/template/.pi/skills/yss-technical-design/SKILL.md +2 -0
  70. package/template/.pi/skills/yss-technical-design/references/engineering-design.schema.json +224 -0
  71. package/template/.pi/skills/yss-technical-design/references/technical-design-common.schema.json +6 -0
  72. package/template/.pi/skills/yss-technical-design/references/technical-design.schema.json +288 -10
  73. package/template/.pi/skills/yss-technical-design/scripts/engineering-design.mjs +30 -0
  74. package/template/.pi/skills/yss-technical-design/scripts/generate-schema.mjs +2 -1
  75. package/template/.pi/skills/yss-technical-design/scripts/validate-technical-design.mjs +20 -8
  76. package/template/.pi/skills/yss-technical-design/tests/engineering-scenarios.mjs +12 -0
  77. package/template/.pi/skills/yss-web-controller/SKILL.md +1 -1
  78. package/template/.pi/skills/yss-web-controller/references/profiles/existing-domain-driven-maven.md +5 -0
  79. package/template/.pi/skills/yss-web-controller/references/profiles/existing-layered-mvc-maven.md +5 -0
  80. package/template/README.md +4 -6
  81. package/template/docs/agents/backend-architecture-profiles.md +4 -0
  82. package/template/docs/agents/yss-skill-registry.yaml +13 -0
  83. package/template/docs/design/templates/prototype-confirmation-template.md +2 -2
  84. package/template/docs/design/templates/prototype-review-checklist.md +2 -2
  85. package/template/docs/plan/templates/market-analysis-template.md +3 -3
  86. package/template/docs/plan/templates/user-pain-points-template.md +3 -3
  87. package/template/docs/process/delivery-preflight.md +72 -0
  88. package/template/docs/process/document-writing.md +5 -1
  89. package/template/docs/process/existing-backend-architecture.md +31 -0
  90. package/template/docs/process/existing-ui-baseline.md +40 -0
  91. package/template/docs/process/frontend-backend-delivery.md +19 -6
  92. package/template/docs/process/implementation-repo-integration.md +6 -0
  93. package/template/docs/process/schemas/backend-architecture-identity.schema.json +111 -14
  94. package/template/docs/process/schemas/delivery-preflight-input.schema.json +158 -0
  95. package/template/docs/process/schemas/delivery-preflight-result.schema.json +159 -0
  96. package/template/docs/process/schemas/digital-human-task-package.schema.json +1 -1
  97. package/template/docs/process/schemas/existing-ui-baseline.schema.json +365 -0
  98. package/template/docs/process/schemas/frontend-delivery-acceptance-v3.schema.json +308 -0
  99. package/template/docs/process/schemas/frontend-strategic-preflight-v2.schema.json +114 -0
  100. package/template/docs/process/schemas/strategic-design-handoff-v5.schema.json +932 -0
  101. package/template/docs/process/schemas/strategic-handoff-export-v2.schema.json +378 -0
  102. package/template/docs/process/strategic-handoff-package.md +21 -13
  103. package/template/docs/user-guide//346/212/200/346/234/257/350/256/276/350/256/241/347/224/250/346/210/267/346/214/207/345/215/227.md +43 -0
  104. package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +83 -67
  105. package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214/347/264/242/345/274/225.md +9 -10
  106. package/template/docs/user-guide//350/256/276/345/244/207/345/200/237/347/224/250/350/264/257/347/251/277/346/241/210/344/276/213.md +12 -9
  107. package/template/scripts/backend-delivery +20 -4
  108. package/template/scripts/lib/approved-execution-context.mjs +106 -0
  109. package/template/scripts/lib/backend-architecture.mjs +12 -0
  110. package/template/scripts/lib/backend-delivery.mjs +10 -6
  111. package/template/scripts/lib/delivery-preflight.mjs +238 -0
  112. package/template/scripts/lib/existing-backend-architecture.mjs +139 -0
  113. package/template/scripts/lib/existing-ui-baseline.mjs +84 -0
  114. package/template/scripts/lib/frontend-delivery.mjs +23 -15
  115. package/template/scripts/lib/implementation-contract-compiler.mjs +19 -5
  116. package/template/scripts/lib/json-schema.mjs +19 -4
  117. package/template/scripts/lib/profile-skill-sync.mjs +26 -0
  118. package/template/scripts/lib/strategic-handoff-consumption.mjs +6 -5
  119. package/template/scripts/lib/strategic-handoff-design-targets.mjs +2 -3
  120. package/template/scripts/lib/strategic-handoff-io.mjs +10 -0
  121. package/template/scripts/lib/strategic-handoff.mjs +47 -29
  122. package/template/scripts/lib/task-package.mjs +11 -3
  123. package/template/scripts/lib/technical-design-boundary.mjs +9 -1
  124. package/template/scripts/lib/ui-baseline.mjs +26 -0
  125. package/template/scripts/lib/user-decision.mjs +4 -1
  126. package/template/scripts/preflight-delivery +14 -0
  127. package/template/scripts/strategic-handoff +19 -4
  128. package/template/scripts/sync-profile-skills +4 -5
  129. package/template/skills-lock.json +15 -15
  130. package/template.snapshot.json +3 -3
  131. package/template/docs/user-guide//346/210/230/346/234/257/350/256/276/350/256/241/345/255/220/351/241/271/347/233/256/347/224/250/346/210/267/346/211/213/345/206/214.md +0 -35
@@ -1,114 +1,130 @@
1
1
  # YSS 用户手册
2
2
 
3
- 面向首次使用与已有项目升级的操作者。本仓是模板源;从模板生成项目实例后再保存真实业务材料。先选对职责,再让 Agent 根据本仓规则执行。
3
+ 本手册帮助项目负责人选择模板、创建或接管项目,并判断 Agent 何时可以继续工作。本仓是 `template-source`;真实业务材料只能写入由 CLI 生成或接管的 `project-instance`。
4
4
 
5
- ## 先选项目
5
+ ## 选择项目家族
6
6
 
7
- | 你的任务 | 选择 | 创建与更新入口 |
7
+ | 你的责任 | 模板与 CLI | 本地终点 |
8
8
  |---|---|---|
9
- | 从想法到发布,统一管理整个业务切片 | 综合模板 `yss-spec-project-template` | `create-yss-spec`:初始化、attach、sync |
10
- | 澄清业务、Spec、原型并交接研发 | 战略模板 `yss-harness-design-agent` | `create-yss-harness-design`:初始化;无 attach/sync |
11
- | 接收已批准上游,统一组织研发 | 通用研发模板 `yss-harness-dev-agent` | `create-yss-harness-dev`:初始化、attach、sync |
12
- | 独立团队承担后端并输出交付包 | 后端模板 `yss-harness-backend-agent` | `create-yss-harness-backend`:init、attach、sync(首版候选) |
13
- | 接收战略及后端交付,承担前端 | 前端模板 `yss-harness-frontend-agent` | `create-yss-harness-frontend`:init、attach、sync(首版候选) |
9
+ | 统一管理从业务问题到实现、验证和发布 | `yss-spec-project-template` / `create-yss-spec` | 完整业务切片验收 |
10
+ | 澄清业务、形成 Spec、页面方案和战略交接 | `yss-harness-design-agent` / `create-yss-harness-design` | Strategic Design Handoff |
11
+ | 设计并实现后端、冻结接口并输出后端交付 | `yss-harness-backend-agent` / `create-yss-harness-backend` | Backend Delivery |
12
+ | 联合接收战略和后端交付、实现并验收前端 | `yss-harness-frontend-agent` / `create-yss-harness-frontend` | Frontend Acceptance |
14
13
 
15
- 通用研发和前后端专职是可选择的组织方式,不要求现有通用项目迁移。采用专职路线时,登记一个统一管理方汇总业务切片,不能把两端自报完成直接相加当作业务验收。
14
+ 专职路线通常按“战略 → 后端 → 前端 → 统一业务验收”接力。每个子项目只确认自己的职责完成;统一管理方绑定同一战略、接口、部署和前端版本后,才能判断整个业务切片是否完成。
16
15
 
17
- 完整协作可以采用“战略 → 后端交付 → 前端联合接收 → 统一业务验收”。综合或通用研发也可承担协调职责,具体责任人和仓库由项目登记,不凭目录推断。
16
+ 既有 `yss-harness-dev-agent` / `create-yss-harness-dev` 实例继续按其固定版本和本地 README 维护。本家族已退出当前项目选型,不自动迁移到综合、后端或前端家族,也不能通过修改 metadata 转换身份。
18
17
 
19
- ## 安装和首次创建
18
+ ## CLI 能力与写入方式
20
19
 
21
- 先确认 Node.js 与 npm 可用,命令要求以所选 CLI README 为准。首次使用推荐下列已发布渠道,三条命令只选择与你职责匹配的一条:
20
+ 先运行所用包的 `--version` 和 `--help`;源码候选版本、npm 已发布版本和实例记录的模板快照是三个不同事实。
22
21
 
23
- ```bash
24
- npm create yss-spec@latest
25
- npm create yss-harness-design@latest
26
- npm create yss-harness-dev@latest
27
- ```
22
+ | 能力 | `create-yss-spec` | 战略、后端、前端专职 CLI |
23
+ |---|---|---|
24
+ | init | 默认命令;写入新目录 | `init`;只接受不存在或空目录 |
25
+ | attach | 必须显式选择 `--dry-run` 或 `--apply` | 默认预览;`--apply` 写入 |
26
+ | sync | 默认写入;`--dry-run`、`--plan`、`--json` 只读 | 默认预览;`--apply` 写入 |
27
+ | diff / doctor | 支持,只读 | 支持,只读 |
28
+ | recover | 无独立命令;失败由事务回滚 | 默认只读诊断;`recover --apply` 恢复未完成事务 |
29
+ | prune | `sync --prune` | `sync --plan --prune` 预览,`sync --apply --prune` 写入 |
30
+ | update / upgrade | 只更新 CLI 程序 | 只更新 CLI 程序 |
28
31
 
29
- 本手册描述 GitHub 当前实现。`@latest` 指 npm 已发布版本,其模板快照可能落后于 GitHub。使用前运行 `npm view <包名> version` 核对;包名占位符须替换。未发布的候选不能用对应的 npm 版本号直接安装。
32
+ `--prune` 只删除仍与可信旧 baseline 相同的退出分发文件。用户改过的旧文件会保留并报告;`--force` 也不能放宽删除、身份、Git、gitlink 或路径安全条件。
30
33
 
31
- 要使用尚未发布的手册版本,从对应 CLI 的 GitHub 固定提交检出,按该仓 README 的候选包步骤构建;检查 `template.snapshot.json` 的 `templateCommit` 与包版本。CLI 初始化使用包内快照,不会实时拉取最新模板。不同家族的快照和版本号分别记录。
34
+ ## 安装、创建与核对
32
35
 
33
- 前后端专职分别使用 `create-yss-harness-backend` / `create-yss-harness-frontend` 首版候选。发布前先从同名 CLI 仓的实际 tgz 安装验收;npm 可用状态以 registry 为准。
36
+ 先确认 npm 中确有需要的版本:
34
37
 
35
38
  ```sh
36
- npx create-yss-harness-backend@latest init --target-dir /absolute/path/to/new-project --project-name 设备借用
37
- npx create-yss-harness-frontend@latest attach --target-dir /absolute/path/to/existing-project
39
+ npm view create-yss-spec version
40
+ npm view create-yss-harness-design version
41
+ npm view create-yss-harness-backend version
42
+ npm view create-yss-harness-frontend version
38
43
  ```
39
44
 
40
- init 只创建不存在或空目录;attach / sync 默认只预览,写入要求 `--apply`。旧仓内脚本实例不兼容,不提供 metadata 转换;新实例记录 schema v2 的模板/core来源与受管基线。冲突整次暂停,显式备份覆盖可用 `--apply --force`,但身份、业务文件和路径保护不可绕过。
45
+ 再选择一个家族创建项目,例如:
46
+
47
+ ```sh
48
+ npm create yss-spec@latest
49
+ npx create-yss-harness-design@latest init --target-dir ./design-project --project-name 设备借用 --business-domain 内部设备管理
50
+ npx create-yss-harness-backend@latest init --target-dir ./backend-project --project-name 设备借用 --business-domain 内部设备管理
51
+ npx create-yss-harness-frontend@latest init --target-dir ./frontend-project --project-name 设备借用 --business-domain 内部设备管理
52
+ ```
53
+
54
+ `@latest` 取得 npm 已发布包,不保证等于 GitHub 当前源码。候选包必须从对应 CLI 仓库构建实际 tgz,并核对 `package.json`、`template.snapshot.json` 的 `templateCommit`、来源状态和摘要;CLI 使用包内快照,不会运行时拉取模板仓。
55
+
56
+ 初始化或 attach 后检查:
41
57
 
42
- 初始化后检查 yss-project.yaml 为 `project-instance`、对应家族 metadata 和 docs/user-guide/用户手册索引.md;进入生成目录再开启 Agent。
58
+ 1. `yss-project.yaml` 是 `project-instance`。
59
+ 2. 只存在本家族 metadata,且 profile 与职责一致。
60
+ 3. 根 `CONTEXT.md`、`AGENTS.md` 和 `docs/user-guide/用户手册索引.md` 可读。
61
+ 4. Git 状态、实现仓登记、验证命令和回滚点符合项目实际情况。
43
62
 
44
63
  ## 第一次让 Agent 工作
45
64
 
46
- 先在生成的项目实例中打开 Agent,发送:
65
+ 在生成的项目实例中发送:
47
66
 
48
67
  ```text
49
- 请先只读检查 yss-project.yaml、根 CONTEXT.md、AGENTS.md,以及存在的 harness-profile.yaml。
68
+ 请先只读检查 yss-project.yaml、根 CONTEXT.md、AGENTS.md 和 harness-profile.yaml。
50
69
  告诉我本仓职责、当前可信阶段、上游输入、缺失证据和下一步。
51
- 发现身份不合法或输入过期时停止并给出恢复办法;先不要写代码。
70
+ 发现身份非法、输入过期或职责越界时停止并给出恢复办法;先不要写代码。
52
71
  ```
53
72
 
54
- 成功时应得到明确的仓库身份和可追踪输入,不是泛泛的开发计划。`template-source` 只能维护可复用模板;真实业务必须在 `project-instance` 中记录。真实业务词汇只登记在实例根 `CONTEXT.md`,不复制本手册示例当作已确认事实。
73
+ 正确结果应说明当前事实、阻塞责任和下一动作。模板文件存在、导入成功、验证包摘要成功或 Agent 自报完成,都不能替代当前批准和 Fresh Verification。
55
74
 
56
- ## 用户确认什么
75
+ ## 用户需要确认什么
57
76
 
58
- | 看到的材料 | 你需要判断 | 确认后的边界 |
77
+ | 看到的材料 | 需要判断 | 确认后的边界 |
59
78
  |---|---|---|
60
- | 目标、范围、规则及反例 | 是否符合业务、哪些不做 | 允许继续设计;不自动批准实现 |
61
- | 页面流程、状态与视觉基线 | 成功、失败、权限和恢复是否完整 | 形成对应产品设计输入 |
62
- | 工程/接口/脚手架方案 | 责任、兼容、数据和回滚是否可接受 | 按本仓角色政策完成适用会签 |
63
- | 当前 Slice Contract | 写哪些仓库与路径、怎么验收 | 必要门禁通过后才能实施 |
64
- | 本轮验证和发布方案 | 覆盖、风险、回滚和交付范围 | 发布及外部承诺仍需生物人 |
79
+ | 目标、范围、规则及反例 | 业务是否正确、哪些不做 | 允许继续设计,不自动批准实现 |
80
+ | 页面流程、状态和视觉基线 | 成功、失败、权限与恢复是否完整 | 形成当前产品设计输入 |
81
+ | 架构、接口和脚手架方案 | 责任、兼容、数据和回滚是否可接受 | 完成对应工程会签 |
82
+ | 当前 Slice Contract | 写哪些仓库与路径、如何验收 | 门禁通过后才允许实施 |
83
+ | 本轮验证和发布方案 | 覆盖、风险、回滚和交付范围 | 发布与外部承诺仍需生物人 |
65
84
 
66
- 具体批准身份和门禁以本仓 `docs/agents/digital-human-roles.yaml`、`docs/process/lifecycle-registry.yaml` 为准。Agent 起草、自报通过或文件中写 `approved` 均不能代替真实批准。`ready-for-human` 是待指定会签;只有可直接实施的切片才使用 `ready-for-agent`。
85
+ 批准身份、范围和失效条件以本地 `digital-human-roles.yaml` 与 `lifecycle-registry.yaml` 为准。编译器只起草合同;`inputs-verified` 只允许继续准备计划和合同;只有当前合同获准、阻塞清除的切片才可进入 `ready-for-agent`。
67
86
 
68
- ## 按路线推进
87
+ ## 当前工作主线
69
88
 
70
- 综合模板按本仓生命周期从分诊、Plan、Spec/功能架构、产品设计、工程契约、Ticket、切片推进到验证与发布。战略模板在业务交接停止;通用研发从批准上游接入;专职两端按交付合同接力。
89
+ 综合模板从分诊、Plan、Spec、产品设计、工程契约、Ticket、实现推进到验证与发布。战略模板在业务交接停止;后端模板消费批准战略并输出可核验后端交付;前端模板联合接收战略、后端、API、数据和 UI 输入后实施前端。
71
90
 
72
- 每一步都让 Agent 说明:消费了哪些当前输入、准备了什么、缺谁确认、怎样检查结果。具体阶段和门禁从本仓注册表读取,不把别的模板阶段编号复制进本仓。
91
+ 涉及交付前提时,先运行只读 `scripts/preflight-delivery`。它只验证原始输入,不初始化项目、不运行构建、不启动服务、不生成批准或收据。导出、导入和实现边界仍要重新验证当前资产。
73
92
 
74
- 跟随 [设备借用贯穿案例](设备借用贯穿案例.md) 练习;战术建模说明见 [战术设计指南](战术设计子项目用户手册.md)。
93
+ 完整演练见[设备借用贯穿案例](设备借用贯穿案例.md),后端技术设计见[技术设计用户指南](技术设计用户指南.md)。
75
94
 
76
- ## 已有项目接管与升级
95
+ ## 接管、同步与恢复
77
96
 
78
- 只有综合/通用研发提供 attach 和 sync。先保存可恢复的 Git 基线,再选择对应包执行;以下是综合示例,通用研发仅将包名替换为 `create-yss-harness-dev`:
97
+ 综合 CLI 示例:
79
98
 
80
- ```bash
81
- npx create-yss-spec@latest attach --target-dir . --project-name "设备借用" --business-domain "内部设备管理" --dry-run
82
- npx create-yss-spec@latest attach --target-dir . --project-name "设备借用" --business-domain "内部设备管理" --apply
99
+ ```sh
100
+ npx create-yss-spec@latest attach --target-dir . --project-name 设备借用 --business-domain 内部设备管理 --dry-run
101
+ npx create-yss-spec@latest attach --target-dir . --project-name 设备借用 --business-domain 内部设备管理 --apply
83
102
  npx create-yss-spec@latest sync --target-dir . --dry-run
84
103
  npx create-yss-spec@latest sync --target-dir .
104
+ npx create-yss-spec@latest sync --target-dir . --plan --prune
85
105
  ```
86
106
 
87
- attach 用于尚未由对应 CLI 管理的既有项目;已存在本家族 metadata 时使用 sync。不要把上面四条不加区分连续执行。正常 sync 保留用户修改并报告 conflict、unsafe 和上游删除项;先审阅实际计划再决定如何处理冲突。源码、.git、gitlink 和挂载点按现有保护规则保留。
88
-
89
- `update`/`upgrade` 更新 CLI 程序,`sync` 更新实例受管模板,两者不同。事务校验失败会回滚本轮文件写入;成功后的撤销使用自己保存的 Git 基线或备份,不用旧 CLI 强制反向同步。
90
-
91
- 战略和专职实例本次没有自动 sync/原地迁移:用同家族新目录比较受管资产,按计划迁移,重验输入和合同,保留原实例回滚。不能跨 profile 覆盖。
107
+ 专职 CLI 示例:
92
108
 
93
- 五家族由 `.yss-template.json`、`.yss-harness-design.json`、`.yss-harness-dev.json`、`.yss-harness-backend.json`、`.yss-harness-frontend.json` 及 profile 判定。不得删除或伪造 metadata 来切换家族。
109
+ ```sh
110
+ npx create-yss-harness-backend@latest attach --target-dir .
111
+ npx create-yss-harness-backend@latest attach --target-dir . --apply
112
+ npx create-yss-harness-backend@latest sync --target-dir . --plan --prune
113
+ npx create-yss-harness-backend@latest sync --target-dir . --apply --prune
114
+ npx create-yss-harness-backend@latest recover --target-dir .
115
+ ```
94
116
 
95
- 异族、多重身份、损坏 metadata、未知或矛盾 profile 会在规划/写入前被拒绝;`--force` 不能绕过,`--dry-run` 同样检查。只有在身份及路径检查通过后,force 才按该命令的覆盖语义生效。遇到拒绝先核对所用家族和目标路径,保留原目录,不用战略 init 强制替代升级。
117
+ attach 用于尚未由该家族管理的普通项目;已有本家族 metadata 时使用 sync。先审阅计划,再选择写入命令。旧 repository-local 实例、未知 schema、多重或异族身份按 CLI 输出处理,不删除 metadata 伪装普通目录。
96
118
 
97
119
  ## 常见卡点
98
120
 
99
- | 现象 | 下一步 |
121
+ | 现象 | 处理 |
100
122
  |---|---|
101
- | Agent 立即开始写代码 | 要求只读分诊,展示当前合同和允许路径 |
102
- | 文件已有但无法继续 | 检查批准、摘要、依赖和 Fresh Verification,不只看文件存在 |
103
- | 前端输入已验证仍不能实现 | inputs-verified 只放行计划/合同准备,先完成合同批准 |
104
- | --force 仍失败 | 查家族、身份、unsafe 与 gitlink,不能靠删 metadata 绕过 |
105
- | npm 创建后没有本手册更新 | 核对 npm 版本与包内模板 SHA,使用已核验候选包或等待正式发布 |
106
- | 独立子项目自报完成 | 统一管理方核对跨仓版本及业务端到端证据 |
107
-
108
- ## 团队与维护者
109
-
110
- 业务人员确认规则和页面;架构与研发落实到冻结接口、当前合同和实际实现仓;Reviewer 独立核验。运行时代码默认进入登记的独立仓,前端优先 pnpm,后端优先根 ./mvnw;缺工具时记录受控例外与实际命令。
111
-
112
- 模板维护者先读 [AGENTS.md](../../AGENTS.md) 和 [流程裁剪](../process/harness-process-tailoring.md),维护 canonical 事实与生成投影,运行分级验证。维护流程不混入用户的日常业务步骤。
113
-
114
- 各模板与 CLI 专项手册见 [用户手册索引](用户手册索引.md)。
123
+ | Agent 立即写代码 | 要求只读分诊,展示当前合同、允许路径和批准证据 |
124
+ | 包验证成功仍不能实现 | 继续完成目标词汇对账、接收、计划和合同批准 |
125
+ | `--force` 仍失败 | 修复身份、冲突、unsafe 路径或 gitlink,不绕过保护 |
126
+ | npm 包缺少新手册 | 比对 npm 版本、CLI 版本和模板 snapshot |
127
+ | 旧手册仍在实例 | 先用 `sync --plan --prune` 判断是否可安全清理 |
128
+ | 单个子项目自报完成 | 由统一管理方核对跨仓版本和端到端业务证据 |
129
+
130
+ 各家族入口见[用户手册索引](用户手册索引.md)。模板维护者另读根 [AGENTS.md](../../AGENTS.md) 和[流程裁剪](../process/harness-process-tailoring.md)。
@@ -2,17 +2,16 @@
2
2
 
3
3
  ## 第一次使用
4
4
 
5
- 1. [YSS 用户手册](用户手册.md):五类项目选型、首次创建、确认与升级。
6
- 2. [设备借用贯穿案例](设备借用贯穿案例.md):输入、提示词、命令、成功标准及异常恢复。
7
- 3. [战术设计指南](战术设计子项目用户手册.md):批准战略如何落到设计和测试。
5
+ 1. [YSS 用户手册](用户手册.md):四个现行家族的选型、CLI、确认、同步和恢复。
6
+ 2. [设备借用贯穿案例](设备借用贯穿案例.md):战略、后端、前端与统一验收的完整练习。
7
+ 3. [技术设计用户指南](技术设计用户指南.md):批准战略或 Spec 如何进入 DDD / layered-mvc 技术设计和实现合同。
8
8
 
9
- ## 专项路线
9
+ ## 按职责进入子项目
10
10
 
11
- - [战略:澄清、设计、交接](https://github.com/iloveZzz/yss-harness-design-agent/blob/main/docs/user-guide/用户手册索引.md)
12
- - [通用研发:接收、合同、实现与验证](https://github.com/iloveZzz/yss-harness-dev-agent/blob/main/docs/user-guide/用户手册索引.md)
13
- - [后端:接口、实现与交付](https://github.com/iloveZzz/yss-harness-backend-agent/blob/main/docs/user-guide/用户手册索引.md)
14
- - [前端:联合接收、页面与验收](https://github.com/iloveZzz/yss-harness-frontend-agent/blob/main/docs/user-guide/用户手册索引.md)
11
+ - [战略设计](https://github.com/iloveZzz/yss-harness-design-agent/blob/main/docs/user-guide/用户手册索引.md)
12
+ - [后端交付](https://github.com/iloveZzz/yss-harness-backend-agent/blob/main/docs/user-guide/用户手册索引.md)
13
+ - [前端接收与验收](https://github.com/iloveZzz/yss-harness-frontend-agent/blob/main/docs/user-guide/用户手册索引.md)
15
14
 
16
- 跨项目导航使用 GitHub 链接;生成实例不需要兄弟仓或 submodules 目录。链接指向各仓 main,实际执行仍核对本地 profile、包版本和固定模板 SHA。
15
+ 既有通用研发实例按其固定版本和本地 README 维护,不再作为新项目入口。生成实例通过 GitHub 链接跨项目导航,但实际操作以本地 profile、CLI `--help`、包版本和模板 snapshot 为准。
17
16
 
18
- CLI 参数详解:[综合 CLI](https://github.com/iloveZzz/create-yss-spec/blob/main/docs/user-guide/create-yss-spec-cli-guide.md)、[战略 CLI](https://github.com/iloveZzz/create-yss-harness-design)、[研发 CLI](https://github.com/iloveZzz/create-yss-harness-dev)。组件工具专项见 [YSS UI MCP](yss-ui-mcp.md)。
17
+ CLI 详解:[综合 CLI](https://github.com/iloveZzz/create-yss-spec/blob/main/docs/user-guide/create-yss-spec-cli-guide.md)、[战略 CLI](https://github.com/iloveZzz/create-yss-harness-design)、[后端 CLI](https://github.com/iloveZzz/create-yss-harness-backend)、[前端 CLI](https://github.com/iloveZzz/create-yss-harness-frontend)。组件专项见 [YSS UI MCP](yss-ui-mcp.md)。
@@ -1,4 +1,4 @@
1
- # 内部设备借用:贯穿五类项目的教学案例
1
+ # 内部设备借用:贯穿四个现行家族的教学案例
2
2
 
3
3
  本文是虚构教学说明,不是已批准 Spec、真实交付包或可直接执行的产品合同。示例路径、规则和标识由学习者在独立 `project-instance` 中确认后落盘;模板源不登记这些业务词汇。
4
4
 
@@ -17,7 +17,7 @@
17
17
 
18
18
  ## 1. 选择工作组织
19
19
 
20
- 综合模板可承载从澄清到业务验收的管理资产。战略模板只负责上游方案;研发既可以交给通用研发模板,也可以交给后端/前端专职模板。后两者必须登记统一管理方及独立实现仓,不把源代码复制进模板。
20
+ 综合模板可承载从澄清到业务验收的管理资产。战略模板只负责上游方案,后端和前端模板按交付协议接力;专职路线必须登记统一管理方及独立实现仓,不把源代码复制进模板。既有通用研发实例只按原固定版本维护,不作为本案例的新建路线。
21
21
 
22
22
  ## 2. 战略方形成可交接输入
23
23
 
@@ -29,18 +29,19 @@
29
29
  列出准备交接的规则、关键场景、版本、批准证据和研发待决事项。
30
30
  ```
31
31
 
32
- 用户逐项核对业务和页面。预期输出为本仓合同要求的已批准战略资产、根词汇、交接描述及证据闭包,不能只交聊天摘要。战略方不在此生成后端工程或冻结工程 API。
32
+ 用户逐项核对业务和页面。预期输出为本仓合同要求的已批准战略资产、根词汇、交接描述及证据闭包,不能只交聊天摘要。战略方不在此生成后端工程或冻结工程 API。UI 有变化时交付已批准原型;确认无 UI 变化的既有工程使用 `existing-ui-baseline`,不能用截图把既有界面伪装成原型。
33
33
 
34
34
  由 Agent 给出实际交接描述路径后,在战略实例执行以下命令。尖括号必须替换为真实路径,输出目录须新建;`--handoff` 是相对源实例的文件路径。
35
35
 
36
36
  ```bash
37
+ node scripts/preflight-delivery --input <战略预检输入.json> --stage export --json
37
38
  node scripts/strategic-handoff export --source-root . --handoff <交接描述相对路径> --output <新包目录> --zip
38
39
  node scripts/strategic-handoff verify --bundle <包目录或ZIP>
39
40
  ```
40
41
 
41
- 预期验包输出 `result: verified` 及包摘要;缺证据或被修改的包会失败。把完整目录/ZIP交给下游,保留版本与摘要,不手改包内文件。
42
+ 预检输入使用 `delivery_kind: strategic-handoff`,绑定交接描述和当前 UI 基线。预期验包输出 `result: verified` 及包摘要;缺证据或被修改的包会失败。把完整目录/ZIP 交给下游,保留版本与摘要,不手改包内文件。
42
43
 
43
- ## 3. 后端或通用研发接收
44
+ ## 3. 后端接收
44
45
 
45
46
  在接收实例运行:
46
47
 
@@ -52,11 +53,11 @@ node scripts/strategic-handoff import --bundle <包目录或ZIP> --target-root .
52
53
  ```text
53
54
  请读取导入收据和包内规则/场景,核对本仓根 CONTEXT.md 并形成正式对账。
54
55
  为“已批准申请领用设备”逐项登记承接、冲突和依赖。
55
- 按当前流程准备战术设计、API Draft/Freeze 和后端 Slice Contract,
56
+ 按当前流程核对既有工程身份,准备技术设计、API Draft/Freeze 和后端 Slice Contract,
56
57
  登记真实实现仓、验证命令和回滚点。合同获准前只准备材料,不写代码。
57
58
  ```
58
59
 
59
- 预期保存导入收据、目标词汇对账、规则/场景承接与当前合同;导入成功不会自动批准这些资产。设备占用竞争应落实到设计与可执行测试,不能只在页面禁用按钮。API 变化回到冻结流程。后端专职只承担后端;通用研发按本仓合同承担实际受影响的两端工作。
60
+ 预期保存导入收据、目标词汇对账、规则/场景承接与当前合同;导入成功不会自动批准这些资产。既有 Java/Maven 工程需要 repository registration、engineering baseline 和 observation manifest 三份当前原始证据。设备占用竞争应落实到设计与可执行测试,不能只在页面禁用按钮;API 变化回到冻结流程。
60
61
 
61
62
  ## 4. 后端交付当前切片
62
63
 
@@ -70,11 +71,12 @@ node scripts/strategic-handoff import --bundle <包目录或ZIP> --target-root .
70
71
  在后端实例执行(交付描述已由实际证据形成):
71
72
 
72
73
  ```bash
74
+ node scripts/preflight-delivery --input <后端预检输入.json> --stage export --json
73
75
  node scripts/backend-delivery export --source-root . --delivery <交付描述相对路径> --output <新交付包目录> --zip
74
76
  node scripts/backend-delivery verify --bundle <交付包目录或ZIP>
75
77
  ```
76
78
 
77
- 预期 `verified`,但 `live_service_checked: false`:这里只验证快照,不能证明环境当前可用。交付包含战略绑定、冻结接口、批准合同、构建部署及成功/失败验证;不把账号密码装入包。实际 API 和版本探测由已登记环境提供,不凭手册假设已有固定端点。
79
+ 后端预检输入使用 `delivery_kind: backend-delivery`,绑定工程身份、技术设计、冻结接口、批准合同、实际制品、部署证据和后端交付源记录。预期 `verified`,但离线验包不能证明环境当前可用。交付不包含账号密码;实际 API 和版本探测由已登记环境提供。
78
80
 
79
81
  ## 5. 前端联合接收与准备
80
82
 
@@ -82,6 +84,7 @@ node scripts/backend-delivery verify --bundle <交付包目录或ZIP>
82
84
 
83
85
  ```bash
84
86
  node scripts/backend-delivery import --bundle <交付包目录或ZIP> --target-root .
87
+ node scripts/preflight-delivery --input <前端接收预检输入.json> --stage accept --json
85
88
  ```
86
89
 
87
90
  战略快照随交付链导入,后端包与战略包分别验证。导入产生接收草稿;核对目标词汇、规则/场景、接口和视觉用例后才能形成正式接收记录。
@@ -99,7 +102,7 @@ node scripts/backend-delivery import --bundle <交付包目录或ZIP> --target-r
99
102
  node scripts/verify-frontend-delivery --root . --slice <切片ID> <接收记录相对路径>
100
103
  ```
101
104
 
102
- 成功是 `inputs-verified` 且 `ready_for_agent: false`。这允许准备计划和合同,正式编码仍须批准且当前的 Slice Contract。前端实现消费冻结 API;发现业务/API缺口回交维护方,不在前端仓悄悄重定义。
105
+ 成功是 `inputs-verified` 且 `ready_for_agent: false`。这允许准备前端工程设计、实现计划和合同,正式编码仍须批准且当前的 Slice Contract。Handoff v5 必须明确 `prototype`、`existing-ui-baseline` 或有原因的 `not-applicable`;发现业务、API 或 UI 基线缺口时回交维护方,不在前端仓悄悄重定义。
103
106
 
104
107
  ## 6. 实现、联调与业务验收
105
108
 
@@ -2,13 +2,29 @@
2
2
  import { parseArgs } from 'node:util';
3
3
  import path from 'node:path';
4
4
  import { exportBackendDelivery, openBackendDelivery, importBackendDelivery } from './lib/backend-delivery.mjs';
5
+ import { read, safe, ensure } from './lib/strategic-handoff-io.mjs';
6
+
7
+ async function preflightExport(values) {
8
+ const root=path.resolve(values['source-root']),delivery=read(safe(root,values.delivery));
9
+ const document=read(safe(root,delivery.slice_contract.ref)),contract=document.slice_contract||document;
10
+ const identity=contract.resolution?.architecture_identity||contract.backend?.architecture_identity||contract.architecture_identity;
11
+ ensure(identity?.schema_version!==2||values['preflight-input'],'preflight-required: 既有工程身份 v2 导出必须提供 --preflight-input <file>;先按 docs/process/delivery-preflight.md 准备源资产清单并执行 export 阶段只读预检');
12
+ if(!values['preflight-input'])return;
13
+ const {preflightDelivery}=await import('./lib/delivery-preflight.mjs');
14
+ const input=read(path.resolve(values['preflight-input']));
15
+ ensure(!input.delivery_kind||input.delivery_kind==='backend-delivery','preflight-scope-conflict: 后端导出只能使用 backend-delivery 清单');
16
+ ensure(path.resolve(root,input.governance_root||'.')===root,'preflight-scope-conflict: 预检治理根与导出来源不同');
17
+ ensure(input.assets?.backend_delivery?.ref===values.delivery,'preflight-scope-conflict: 预检未绑定本次导出的 delivery 源文件');
18
+ const result=await preflightDelivery({...input,delivery_kind:'backend-delivery'},{stage:'export',root});
19
+ if(result.exit_code!==0){const error=new TypeError('delivery-preflight-blocked: 请按每项 recovery 补证,再从正常导出入口重试');error.preflight=result;throw error;}
20
+ }
5
21
  try {
6
- const {values,positionals}=parseArgs({allowPositionals:true,options:{'source-root':{type:'string'},delivery:{type:'string'},output:{type:'string'},zip:{type:'boolean'},bundle:{type:'string'},'target-root':{type:'string'}}});
22
+ const {values,positionals}=parseArgs({allowPositionals:true,options:{'source-root':{type:'string'},delivery:{type:'string'},output:{type:'string'},zip:{type:'boolean'},bundle:{type:'string'},'target-root':{type:'string'},'preflight-input':{type:'string'}}});
7
23
  if(positionals.length!==1)throw new TypeError('必须指定 export / verify / import');
8
24
  let result;
9
- if(positionals[0]==='export'&&values['source-root']&&values.delivery&&values.output)result=await exportBackendDelivery({sourceRoot:values['source-root'],deliveryRef:values.delivery,output:values.output,zip:values.zip});
25
+ if(positionals[0]==='export'&&values['source-root']&&values.delivery&&values.output){await preflightExport(values);result=await exportBackendDelivery({sourceRoot:values['source-root'],deliveryRef:values.delivery,output:values.output,zip:values.zip});}
10
26
  else if(positionals[0]==='verify'&&values.bundle)result=await openBackendDelivery(path.resolve(values.bundle),b=>({result:'verified',delivery_id:b.delivery.delivery_id,version:b.delivery.version,bundle_digest:b.manifest.bundle_digest,live_service_checked:false}));
11
27
  else if(positionals[0]==='import'&&values.bundle&&values['target-root'])result=await importBackendDelivery({bundle:path.resolve(values.bundle),targetRoot:values['target-root']});
12
- else throw new TypeError('用法: backend-delivery export --source-root <repo> --delivery <ref> --output <new-dir> [--zip] | verify --bundle <dir|zip> | import --bundle <dir|zip> --target-root <repo>');
28
+ else throw new TypeError('用法: backend-delivery export --source-root <repo> --delivery <ref> --output <new-dir> [--preflight-input <file>] [--zip] | verify --bundle <dir|zip> | import --bundle <dir|zip> --target-root <repo>');
13
29
  process.stdout.write(`${JSON.stringify(result,null,2)}\n`);
14
- } catch(error) { process.stderr.write(`${JSON.stringify({result:'blocked',error:error.message})}\n`);process.exitCode=1; }
30
+ } catch(error) { process.stderr.write(`${JSON.stringify({result:'blocked',error:error.message,...(error.preflight?{preflight:error.preflight}:{})})}\n`);process.exitCode=1; }
@@ -0,0 +1,106 @@
1
+ import path from 'node:path';
2
+ import { readFileSync } from 'node:fs';
3
+ import { ROOT, read, parse, safe, hash, digest, schema } from './strategic-handoff-io.mjs';
4
+ import { countersignRuleForGate } from './digital-human-roles.mjs';
5
+ import { validateApprovalRecord } from './approval-record.mjs';
6
+ import { assertImplementationDecision } from './user-decision.mjs';
7
+ import { loadSkillRegistry } from './skill-registry.mjs';
8
+
9
+ const contexts=new WeakMap();
10
+ const gateId='gate.slice-contract-approved';
11
+ const check=(ok,code,message)=>{if(!ok){const error=new TypeError(`${code}: ${message}`);error.code=code;throw error;}};
12
+ const same=(a,b)=>digest(a)===digest(b);
13
+ const ioFor=root=>({root,read:ref=>readFileSync(safe(root,path.relative(root,ref).split(path.sep).join('/')))});
14
+
15
+ /** Existing registrations require persisted input sections; array properties disappear in JSON. */
16
+ export function assertExistingSliceStructure(contract) {
17
+ const identity=contract?.resolution?.architecture_identity;
18
+ if(identity?.schema_version!==2||identity.source_kind!=='existing-registration')return;
19
+ const object=value=>value!==null&&typeof value==='object'&&!Array.isArray(value);
20
+ check(object(contract.lifecycle_refs),'EXECUTION_CONTRACT_INVALID','既有工程 Slice lifecycle_refs 必须是对象');
21
+ for(const field of ['ticket','engineering_baseline'])check(typeof contract.lifecycle_refs[field]==='string'&&contract.lifecycle_refs[field].trim(),'EXECUTION_CONTRACT_INVALID',`既有工程 Slice 缺少 lifecycle_refs.${field}`);
22
+ check(object(contract.readiness),'EXECUTION_CONTRACT_INVALID','既有工程 Slice readiness 必须是对象');
23
+ for(const field of ['blockers','stale_inputs','not_applicable'])check(Array.isArray(contract.readiness[field]),'EXECUTION_CONTRACT_INVALID',`既有工程 Slice readiness.${field} 必须是数组`);
24
+ }
25
+
26
+ /** Reads original local approval; a contract's own approved status never establishes permission. */
27
+ export function verifySliceContractApproval(binding,{root=process.cwd(),contract:expected}={}) {
28
+ root=path.resolve(root);
29
+ check(binding?.ref&&binding?.digest&&binding?.approval_ref,'EXECUTION_APPROVAL_REQUIRED','需要当前持久化 Slice 的 ref/digest/approval_ref');
30
+ const bytes=readFileSync(safe(root,binding.ref));
31
+ check(hash(bytes)===binding.digest,'EXECUTION_CONTRACT_STALE','Slice 原始字节与绑定不一致');
32
+ const document=parse(bytes),contract=document.slice_contract||document;
33
+ check(contract.schema_version===2&&contract.status==='approved'&&typeof contract.contract_id==='string'&&contract.contract_id&&typeof contract.contract_version==='string'&&contract.contract_version&&typeof contract.slice_id==='string'&&contract.slice_id,'EXECUTION_CONTRACT_INVALID','需要已批准且有身份的持久化 Slice v2');
34
+ assertExistingSliceStructure(contract);
35
+ check((!binding.id||binding.id===contract.contract_id)&&(!binding.version||binding.version===contract.contract_version),'EXECUTION_CONTRACT_CONFLICT','当前合同身份或版本不匹配');
36
+ if(expected)check(same(expected.slice_contract||expected,contract),'EXECUTION_CONTRACT_CONFLICT','调用方合同与持久化原字节不一致');
37
+ const roles=read(safe(root,'docs/agents/digital-human-roles.yaml'));
38
+ const approval=read(safe(root,binding.approval_ref));
39
+ if(!countersignRuleForGate(roles.gate_policy,gateId)&&roles.gate_policy.orchestrator?.includes(gateId)) {
40
+ // The current lifecycle already owns this gate. Consume its checkpoint and existing
41
+ // implementation-scope decision instead of inventing an approval-record countersignature.
42
+ check(approval?.gates&&approval?.human_review&&!approval.gate_id,'EXECUTION_APPROVAL_PROTOCOL','当前主控 gate 需要生命周期 checkpoint,不接受伪造 approval-record');
43
+ schema(approval,'docs/process/schemas/lifecycle-checkpoint.schema.json');
44
+ const gate=approval.gates?.[gateId],review=approval.human_review||{};
45
+ check(approval.repository_mode==='project-instance'&&approval.status!=='blocked'&&approval.blockers.length===0,'EXECUTION_APPROVAL_BLOCKED','主控 checkpoint 仍有阻断或不是产品实例');
46
+ check(gate?.status==='approved'&&gate.subject_ref===binding.ref,'EXECUTION_APPROVAL_SCOPE','主控 gate 未批准当前持久化 Slice');
47
+ check(review.implementation?.slice_contract_ref===binding.ref,'EXECUTION_APPROVAL_SCOPE','实施批准不指向当前 Slice 原始文件');
48
+ assertImplementationDecision({...review.implementation,user_decisions:review.user_decisions||[]},{...ioFor(root),rolesDoc:roles});
49
+ } else {
50
+ // Historical source profiles that declared this a countersign gate retain their policy.
51
+ validateApprovalRecord(approval,{...ioFor(root),rolesDoc:roles,requireApproved:true});
52
+ check(approval.gate_id===gateId&&approval.artifact_bindings?.some(item=>item.id===contract.contract_id&&item.version===contract.contract_version&&item.digest===binding.digest),'EXECUTION_APPROVAL_SCOPE','源会签未绑定当前 Slice 的身份、版本和字节');
53
+ }
54
+ return {contract,binding:structuredClone(binding),root};
55
+ }
56
+
57
+ function executionBasis(verified,{allowCompilerDrift=false}={}) {
58
+ const {contract}=verified,resolution=contract.resolution||{};
59
+ const compiler=read(safe(ROOT,'.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml'));
60
+ if(!allowCompilerDrift)for(const [section,fields] of Object.entries(compiler.slice_contract_required))for(const field of fields)check(Object.hasOwn(section==='root'?contract:contract[section]||{},field),'EXECUTION_CONTRACT_INVALID',`合同缺少 ${section}.${field}`);
61
+ check(Array.isArray(contract.common?.allowed_write_paths)&&contract.common.allowed_write_paths.length>0&&contract.common.allowed_write_paths.every(value=>typeof value==='string'&&value.trim()),'EXECUTION_SCOPE_MISSING','合同缺少已批准写范围');
62
+ check(Array.isArray(contract.readiness?.blockers)&&!contract.readiness.blockers.length&&Array.isArray(contract.readiness?.stale_inputs)&&!contract.readiness.stale_inputs.length,'EXECUTION_CONTRACT_STALE','合同就绪条件仍有阻断或过期输入');
63
+ if(!allowCompilerDrift)check(resolution.registry_digest===digest(loadSkillRegistry()).slice(7)&&resolution.compiler_contract_digest===digest(compiler).slice(7),'EXECUTION_CONTRACT_STALE','编译依据已改变,应重新编译批准');
64
+ check(resolution.freshness==='current','EXECUTION_CONTRACT_STALE','resolution 不是 current');
65
+ if(resolution.architecture_identity)check(resolution.architecture_identity_digest===digest(resolution.architecture_identity).slice(7),'EXECUTION_CONTRACT_STALE','编译架构身份摘要不一致');
66
+ return verified;
67
+ }
68
+
69
+ export function createApprovedExecutionContext(binding,options={}) {
70
+ const verified=executionBasis(verifySliceContractApproval(binding,options));
71
+ const context=Object.freeze({kind:'approved-slice-execution-context'});
72
+ contexts.set(context,{binding:verified.binding,root:verified.root,allowCompilerDrift:false});
73
+ return context;
74
+ }
75
+
76
+ /** A prior approved scope may authenticate bounded output while current compiler facts are recomputed. */
77
+ export function createApprovedRecompilationContext(binding,options={}) {
78
+ const verified=executionBasis(verifySliceContractApproval(binding,options),{allowCompilerDrift:true});
79
+ const context=Object.freeze({kind:'approved-slice-recompilation-context'});
80
+ contexts.set(context,{binding:verified.binding,root:verified.root,allowCompilerDrift:true});
81
+ return context;
82
+ }
83
+
84
+ /** Revalidate original bytes on every boundary; a serialized/caller-invented context is rejected. */
85
+ export function assertApprovedExecutionContext(context,{root=process.cwd(),contract,architectureIdentity,architectureEvidence,technicalDesign,sliceId}={}) {
86
+ const saved=contexts.get(context);
87
+ check(saved&&saved.root===path.resolve(root),'EXECUTION_CONTEXT_UNTRUSTED','只允许从当前原始 Slice 与本地批准生成的执行上下文');
88
+ const verified=executionBasis(verifySliceContractApproval(saved.binding,{root,contract}),{allowCompilerDrift:saved.allowCompilerDrift});
89
+ const current=verified.contract,resolution=current.resolution;
90
+ if(sliceId)check(current.slice_id===sliceId,'EXECUTION_SCOPE_CONFLICT','执行上下文属于另一切片');
91
+ if(architectureIdentity)check(same(resolution.architecture_identity,architectureIdentity),'EXECUTION_INPUT_REPLACED','执行上下文不允许替换架构身份或固定源码输入');
92
+ if(architectureEvidence)check(same(resolution.architecture_evidence,architectureEvidence),'EXECUTION_INPUT_REPLACED','执行上下文不允许替换原始架构证据');
93
+ if(technicalDesign) {
94
+ const binding=resolution.technical_design;
95
+ check(binding?.ref&&binding.digest,'EXECUTION_DESIGN_MISSING','Slice 未绑定当前技术设计');
96
+ const bytes=readFileSync(safe(root,binding.ref));
97
+ check(hash(bytes)===binding.digest&&same(parse(bytes),technicalDesign),'EXECUTION_INPUT_REPLACED','执行上下文不允许替换技术设计');
98
+ }
99
+ return {allowed_write_paths:[...current.common.allowed_write_paths],contract:current};
100
+ }
101
+
102
+ export function approvedExecutionBinding(context) {
103
+ const saved=contexts.get(context);
104
+ check(saved,'EXECUTION_CONTEXT_UNTRUSTED','不能序列化未验证的执行上下文');
105
+ return structuredClone(saved.binding);
106
+ }
@@ -1,5 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { loadSkillRegistry } from "./skill-registry.mjs";
3
+ import { validateExistingArchitecture, verifyExistingArchitecture } from "./existing-backend-architecture.mjs";
3
4
 
4
5
  export function architectureDigest(value) {
5
6
  const stable = (item) => Array.isArray(item) ? item.map(stable) : item && typeof item === "object"
@@ -9,6 +10,8 @@ export function architectureDigest(value) {
9
10
 
10
11
  export function validateArchitectureIdentity(identity, registry = loadSkillRegistry()) {
11
12
  if (!identity || typeof identity !== "object") throw new TypeError("缺少 architecture_identity;请从工程基线重新编译");
13
+ if (identity.schema_version === 2) return validateExistingArchitecture(identity, registry);
14
+ if (identity.schema_version !== undefined || identity.source_kind !== undefined) throw new TypeError("不支持的 architecture_identity 来源或版本");
12
15
  const profile = registry.architecture_profiles?.[identity.architecture_profile];
13
16
  if (!profile || identity.architecture_family !== profile.architecture_family || identity.generator_skill !== profile.generator_skill) {
14
17
  throw new TypeError("architecture_identity 的架构族、Profile 或生成器不匹配");
@@ -28,6 +31,15 @@ export function validateArchitectureIdentity(identity, registry = loadSkillRegis
28
31
  return profile;
29
32
  }
30
33
 
34
+ // Existing projects must present original on-disk evidence, not three copies supplied by a caller.
35
+ export function verifyArchitectureEvidence(identity, evidence, { root, registry = loadSkillRegistry(), execution } = {}) {
36
+ validateArchitectureIdentity(identity, registry);
37
+ if (identity.schema_version === 2) return verifyExistingArchitecture(identity, evidence, { root, registry, execution });
38
+ if (!evidence?.engineering_baseline || !evidence?.repository_registration || !evidence?.manifest) throw new TypeError("缺少工程基线、仓库登记或 Manifest 架构证据");
39
+ assertArchitectureAgreement(identity, evidence, registry);
40
+ return { source_kind: "scaffold", bindings: evidence };
41
+ }
42
+
31
43
  export function assertArchitectureAgreement(identity, evidence, registry) {
32
44
  validateArchitectureIdentity(identity, registry);
33
45
  for (const [name, source] of Object.entries(evidence ?? {})) {
@@ -1,3 +1,4 @@
1
+ import { verifySliceContractApproval } from './approved-execution-context.mjs';
1
2
  import { cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync } from 'node:fs';
2
3
  import path from 'node:path';
3
4
  import { tmpdir } from 'node:os';
@@ -17,6 +18,7 @@ function boundFile(root, binding) {
17
18
 
18
19
  async function approvedFile(root, binding, gate) {
19
20
  const bytes=boundFile(root,binding);
21
+ if(gate==='gate.slice-contract-approved'){verifySliceContractApproval(binding,{root});return bytes;}
20
22
  const record=read(safe(root,binding.approval_ref));
21
23
  const roles=sourceApprovalPolicy(read(safe(root,'docs/agents/digital-human-roles.yaml')));
22
24
  await sourceApproval(record,roles,root);
@@ -38,7 +40,7 @@ function verification(root, binding, basis, kind) {
38
40
  return record;
39
41
  }
40
42
 
41
- export async function inspectBackendDelivery(root, ref) {
43
+ export async function inspectBackendDelivery(root, ref, { readOnly = false } = {}) {
42
44
  project(root);
43
45
  const delivery=read(safe(root,ref));
44
46
  schema(delivery,'docs/process/schemas/backend-delivery.schema.json');
@@ -57,7 +59,7 @@ export async function inspectBackendDelivery(root, ref) {
57
59
  verification(root,delivery.verification.deployment,basis,'backend-deployment');
58
60
  return openBundle(safe(root,delivery.strategic_bundle_ref),bundle=>{
59
61
  ensure(bundle.manifest.bundle_digest===delivery.strategic_bundle_digest,'后端交付与战略版本不一致');
60
- if(bundle.handoff.schema_version===4){
62
+ if([4,5].includes(bundle.handoff.schema_version)){
61
63
  const route=bundle.handoff.consumer_routes.find(item=>item.capability==='backend-technical-design');
62
64
  ensure(route&&route.activation!=='not-applicable'&&delivery.strategic_route_id===route.route_id,'后端交付未绑定当前 backend-technical-design route_id');
63
65
  }
@@ -71,7 +73,7 @@ export async function inspectBackendDelivery(root, ref) {
71
73
  }
72
74
  ensure(delivery.scope.operation_ids.every(id=>tests.operation_ids.includes(id)),'后端契约验证未覆盖交付接口');
73
75
  return {delivery,basis};
74
- });
76
+ }, { readOnly });
75
77
  }
76
78
 
77
79
  function validManifest(manifest,root) {
@@ -168,9 +170,11 @@ export async function importBackendDelivery({bundle,targetRoot}) {
168
170
  write(staging,'import-receipt.json',json(receipt));
169
171
  const strategicHandoff={import_receipt_ref:strategic.receipt_ref,bundle_digest:strategicReceipt.bundle_digest,...(trace.route_id?{route_id:trace.route_id}:{}),context_reconciliation_ref:'',rows:trace.rows.map(({tactical_refs,test_seam_refs,...row})=>({...row,frontend_case_refs:[]}))};
170
172
  if(strategicReceipt.schema_version===2){
171
- ensure(frontendRoute,'Handoff v4 Import Receipt 未选择 frontend-engineering-design 能力');
172
- const preflightRef=frontendRoute.artifact_refs.find(item=>item.endsWith('frontend-strategic-preflight-draft.json'));ensure(preflightRef,'Handoff v4 缺少 Frontend Strategic Preflight 草案');
173
- write(staging,'frontend-acceptance-draft.json',json({schema_version:2,status:'draft',slice_id:b.delivery.scope.slice_id,strategic_preflight:{ref:preflightRef,digest:hash(readFileSync(safe(target,preflightRef)))},backend_dependency:{mode:'required',route_id:'route.backend'},backend_delivery:{import_receipt_ref:`${ref}/import-receipt.json`,bundle_digest:b.manifest.bundle_digest},strategic_handoff:strategicHandoff,frontend_cases:[]}));
173
+ ensure(frontendRoute,'Import Receipt 未选择 frontend-engineering-design 能力');
174
+ const preflightRef=frontendRoute.artifact_refs.find(item=>item.endsWith('frontend-strategic-preflight-draft.json'));ensure(preflightRef,'缺少 Frontend Strategic Preflight 草案');
175
+ const preflight=read(safe(target,preflightRef));
176
+ ensure([1,2].includes(preflight.schema_version),'未知 Frontend Strategic Preflight 版本');
177
+ write(staging,'frontend-acceptance-draft.json',json({schema_version:preflight.schema_version===2?3:2,...(preflight.schema_version===2?{ui_baseline_kind:preflight.ui_baseline_kind}:{}),status:'draft',slice_id:b.delivery.scope.slice_id,strategic_preflight:{ref:preflightRef,digest:hash(readFileSync(safe(target,preflightRef)))},backend_dependency:{mode:'required',route_id:b.delivery.strategic_route_id},backend_delivery:{import_receipt_ref:`${ref}/import-receipt.json`,bundle_digest:b.manifest.bundle_digest},strategic_handoff:strategicHandoff,frontend_cases:[]}));
174
178
  }else write(staging,'frontend-acceptance-draft.json',json({schema_version:1,status:'draft',slice_id:b.delivery.scope.slice_id,backend_delivery:{import_receipt_ref:`${ref}/import-receipt.json`,bundle_digest:b.manifest.bundle_digest},strategic_handoff:strategicHandoff,frontend_cases:[]}));
175
179
  ensure(!existsSync(destination),'后端包导入并发冲突');renameSync(staging,destination);
176
180
  return {result:'imported-pending-acceptance',receipt_ref:`${ref}/import-receipt.json`,acceptance_ref:`${ref}/frontend-acceptance-draft.json`};