openspec-sdd-e2e-kit 0.1.0

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 (38) hide show
  1. package/README.md +63 -0
  2. package/bin/sdd-e2e-kit.mjs +53 -0
  3. package/kit/.codex/skills/feature-to-e2e/SKILL.md +188 -0
  4. package/kit/.codex/skills/feature-to-e2e/agents/openai.yaml +4 -0
  5. package/kit/.codex/skills/openspec-apply-change/SKILL.md +180 -0
  6. package/kit/.codex/skills/openspec-archive-change/SKILL.md +157 -0
  7. package/kit/.codex/skills/openspec-continue-change/SKILL.md +136 -0
  8. package/kit/.codex/skills/openspec-explore/SKILL.md +292 -0
  9. package/kit/.codex/skills/openspec-full-spec-discovery/SKILL.md +356 -0
  10. package/kit/.codex/skills/openspec-full-spec-discovery/references/backlog-row-to-main-spec.md +447 -0
  11. package/kit/.codex/skills/openspec-new-change/SKILL.md +92 -0
  12. package/kit/.codex/skills/openspec-propose/SKILL.md +132 -0
  13. package/kit/.codex/skills/spec-to-gherkin/SKILL.md +686 -0
  14. package/kit/SDD_E2E_FLOW.md +268 -0
  15. package/kit/manifest.json +78 -0
  16. package/kit/openspec/config.yaml +18 -0
  17. package/kit/openspec/schemas/sdd-e2e/schema.yaml +128 -0
  18. package/kit/openspec/schemas/sdd-e2e/templates/acceptance-coverage.md +9 -0
  19. package/kit/openspec/schemas/sdd-e2e/templates/design.md +29 -0
  20. package/kit/openspec/schemas/sdd-e2e/templates/feature.feature +13 -0
  21. package/kit/openspec/schemas/sdd-e2e/templates/proposal.md +23 -0
  22. package/kit/openspec/schemas/sdd-e2e/templates/spec.md +21 -0
  23. package/kit/openspec/schemas/sdd-e2e/templates/tasks.md +16 -0
  24. package/kit/openspec/schemas/sdd-e2e/templates/test-cases.md +35 -0
  25. package/kit/openspec/schemas/sdd-e2e.yaml +160 -0
  26. package/kit/openspec/sdd-e2e-flow.md +290 -0
  27. package/kit/openspec/sdd-e2e-maintenance.md +98 -0
  28. package/kit/scripts/sdd/check-report.mjs +34 -0
  29. package/kit/scripts/sdd/lib.mjs +290 -0
  30. package/kit/scripts/sdd/lint-features.mjs +60 -0
  31. package/kit/scripts/sdd/lint-tasks.mjs +41 -0
  32. package/kit/scripts/sdd/self-test.mjs +185 -0
  33. package/kit/scripts/sdd/summarize-acceptance.mjs +41 -0
  34. package/package.json +19 -0
  35. package/src/check.mjs +86 -0
  36. package/src/diff.mjs +101 -0
  37. package/src/install.mjs +159 -0
  38. package/src/lib.mjs +221 -0
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # OpenSpec SDD-E2E Kit
2
+
3
+ A portable OpenSpec project-local schema, Codex skill overlay, and SDD/E2E gate scripts for phase-based Spec Driven Development.
4
+
5
+ ## Usage
6
+
7
+ From a target project root, install the kit assets with one command:
8
+
9
+ ```bash
10
+ npx openspec-sdd-e2e-kit
11
+ ```
12
+
13
+ Preview the writes first:
14
+
15
+ ```bash
16
+ npx openspec-sdd-e2e-kit --dry-run
17
+ ```
18
+
19
+ From this repository:
20
+
21
+ ```bash
22
+ node bin/sdd-e2e-kit.mjs
23
+ node bin/sdd-e2e-kit.mjs check /path/to/project
24
+ node bin/sdd-e2e-kit.mjs diff /path/to/project
25
+ node bin/sdd-e2e-kit.mjs install /path/to/project
26
+ ```
27
+
28
+ After publishing or linking as a package:
29
+
30
+ ```bash
31
+ sdd-e2e-kit
32
+ sdd-e2e-kit check /path/to/project
33
+ sdd-e2e-kit diff /path/to/project
34
+ sdd-e2e-kit install /path/to/project
35
+ ```
36
+
37
+ ## Commands
38
+
39
+ - Running without a command installs the kit into the current working directory.
40
+ - `check`: verify required assets and `package.json` `sdd:*` scripts exist.
41
+ - `diff`: compare a target project against the kit baseline.
42
+ - `install`: copy assets and merge `sdd:*` scripts. Changed target files are not overwritten unless `--force` is used.
43
+ - `update`: alias for `install`; still conservative by default.
44
+
45
+ ## Installed Assets
46
+
47
+ The installable baseline lives in `kit/` and includes:
48
+
49
+ - OpenSpec `sdd-e2e` schema and templates
50
+ - SDD-E2E workflow documentation
51
+ - Codex OpenSpec skills and E2E helper skills
52
+ - `scripts/sdd/*` semantic gate scripts
53
+ - `package.json` `sdd:*` script definitions from `kit/manifest.json`
54
+
55
+ ## Target Project Validation
56
+
57
+ Run these in a target project after install:
58
+
59
+ ```bash
60
+ openspec schema validate sdd-e2e --json
61
+ openspec schemas --json
62
+ pnpm sdd:self-test
63
+ ```
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
7
+ const argv = process.argv.slice(2);
8
+ const [firstArg, ...remainingArgs] = argv;
9
+ const commands = {
10
+ check: "src/check.mjs",
11
+ diff: "src/diff.mjs",
12
+ install: "src/install.mjs",
13
+ update: "src/install.mjs",
14
+ };
15
+
16
+ function help() {
17
+ console.log([
18
+ "Usage: sdd-e2e-kit [command] [target] [options]",
19
+ "",
20
+ "Running without a command installs the kit into the current working directory.",
21
+ "",
22
+ "Commands:",
23
+ " check Check whether a project has the kit assets and scripts",
24
+ " diff Compare a project against the kit baseline",
25
+ " install Install kit assets into a project",
26
+ " update Alias for install; conflicts still require --force",
27
+ "",
28
+ "Examples:",
29
+ " sdd-e2e-kit",
30
+ " sdd-e2e-kit --dry-run",
31
+ " sdd-e2e-kit check /path/to/project",
32
+ " sdd-e2e-kit diff /path/to/project",
33
+ " sdd-e2e-kit install /path/to/project",
34
+ ].join("\n"));
35
+ }
36
+
37
+ if (firstArg === "--help" || firstArg === "-h") {
38
+ help();
39
+ process.exit(0);
40
+ }
41
+
42
+ const command = firstArg && commands[firstArg] ? firstArg : "install";
43
+ const args = firstArg && commands[firstArg] ? remainingArgs : argv;
44
+ const script = commands[command];
45
+
46
+ if (firstArg && !commands[firstArg] && !firstArg.startsWith("-")) {
47
+ console.error(`Unknown command: ${firstArg}`);
48
+ help();
49
+ process.exit(1);
50
+ }
51
+
52
+ const result = spawnSync(process.execPath, [path.join(root, script), ...args], { stdio: "inherit" });
53
+ process.exit(result.status ?? 1);
@@ -0,0 +1,188 @@
1
+ ---
2
+ name: feature-to-e2e
3
+ description: 在需求开发完成后或某个 OpenSpec phase 完成后,根据 .feature BDD 验收场景直接操作真实页面,支持按 @phase/@validation 标签筛选小范围场景,生成并运行 Playwright 脚本,记录交互步骤、断言、证据和执行结果,用于判断实现逻辑是否符合 feature 描述。适用于实现后的验收或 phase 级 acceptance gate,不用于搭建 Cucumber 基建或长期 CI 回归套件。
4
+ ---
5
+
6
+ # Skill: Feature 到 E2E 验收验证
7
+
8
+ ## 定位
9
+
10
+ `feature-to-e2e` 用于**开发完成后的功能验收**,也用于 OpenSpec SDD 流程中**单个 phase 完成后的切片验收**。
11
+
12
+ 以 `.feature` 文件为验收真相,用真实浏览器打开页面、点击、输入、观察状态,并把实际操作沉淀为可运行的 Playwright Test。生成脚本默认尽量复用一个浏览器窗口、一个 context、一个 page,按 feature 中的 Scenario 顺序执行。最终输出每个 Scenario 的验证结果:`passed`、`mismatch`、`blocked`、`manual` 或 `gap-pending`。
13
+
14
+ 默认目标是回答一个问题:**当前实现是否符合 feature 描述?**
15
+
16
+ 在 phase 验证模式下,默认目标是回答:**当前 phase 的实现是否满足带有同一 `@phase:<id>` 标签的 Scenario?**
17
+
18
+ Phase 验证默认是 **acceptance gate**,不是 smoke gate。只验证每个 phase 的代表性主链路不足以判断实施质量;除非用户明确要求 smoke,否则必须覆盖当前 phase 下所有不含 `@gap-pending` 且 `@validation` 可自动化的 P0/P1 Scenario,尤其是输入校验、失败降级、竞态、防重复、条件渲染、跨视图同步等边界场景。
19
+
20
+ 如果 change 使用 `schema: sdd-e2e`,本 skill 是 `openspec/schemas/sdd-e2e.yaml` 中 `phaseAcceptance` gate 的执行器。生成报告后必须能被 `pnpm sdd:phase <change> <phase>` 检查。
21
+
22
+ ## 不做什么
23
+
24
+ - 不生成 Cucumber runner、step definitions、World 或 hooks。
25
+ - 不把页面当前行为反向改写成规格。
26
+ - 不为了通过测试删除、弱化或跳过 feature 中的业务断言。
27
+ - 不默认建设 CI 回归套件、复杂 fixture 平台或长期测试资产。
28
+ - 不默认做异常注入、网络 mock、性能测试或跨浏览器矩阵,除非 feature 明确要求或用户明确指定。
29
+ - 不猜测登录账号、验证码、token、权限或绕过鉴权方式。
30
+ - 不在用户只要求某个 phase 时全量验证整个 features 目录。
31
+ - 不把 phase smoke 结果当作 phase 完成条件;smoke 只能证明入口和基础链路可用,不能替代边界 Scenario 验收。
32
+
33
+ ## 输入
34
+
35
+ - 一个 `.feature` 文件或一个 features 目录。
36
+ - 可选的场景筛选条件:`@phase:<id>`、`@validation:<type>`、单个 Scenario 名称或用户指定的 tags。
37
+ - 应用入口 URL、dev server 命令或已有 Playwright `baseURL`。
38
+ - 登录态、测试账号、`storageState`、登录 helper 或其他可执行认证方式。
39
+ - 必要的测试数据、seed 方式或可安全操作的 E2E 测试数据范围。
40
+ - 项目已有 Playwright config、测试目录、脚本和 helper。
41
+
42
+ 缺少入口、鉴权处理方式或关键测试数据时,先暂停并向用户询问具体缺口。
43
+
44
+ 如果 features 中存在 `@phase:*` 标签但用户没有指定验证范围,不要默认全量执行所有 phase;先询问要验证哪个 phase,或在用户明确要求“全量验收”时再执行全量。
45
+
46
+ ## 输出
47
+
48
+ 把产物放在项目 Playwright config 可发现的测试目录下。推荐最小结构:
49
+
50
+ ```text
51
+ <testDir>/bdd/<feature-slug>/
52
+ ├── <feature-slug>.validation.spec.ts
53
+ ├── validation-report.md
54
+ └── evidence/
55
+ └── screenshots/ # 仅在需要时生成
56
+ ```
57
+
58
+ Phase 验证模式推荐结构:
59
+
60
+ ```text
61
+ <testDir>/bdd/<feature-slug>/
62
+ ├── <phase-id>.validation.spec.ts
63
+ ├── validation-report.<phase-id>.md
64
+ └── evidence/
65
+ └── screenshots/
66
+ ```
67
+
68
+ `schema: sdd-e2e` 的 phase report 默认写入:
69
+
70
+ ```text
71
+ specs/e2e/bdd/<change>/validation-report.<phase-id>.md
72
+ ```
73
+
74
+ 必须产出:
75
+
76
+ - 可运行的 Playwright Test 脚本。
77
+ - 脚本默认在单一窗口上下文中顺序执行;无法这样执行时说明原因。
78
+ - 明确的运行命令。
79
+ - 每个 Scenario 的执行结果。
80
+ - 报告中明确记录验证范围:全量、`@phase:<id>`、`@validation:<type>` 或具体 Scenario。
81
+ - Scenario coverage:列出选中的 Scenario 总数、已自动化数、passed/mismatch/blocked/manual/gap 数;phase acceptance gate 要求自动化范围内 Scenario 100% 有结果。
82
+ - 失败分类:产品 `mismatch`、环境/数据 `blocked`,或测试脚本问题并已修复重跑。
83
+
84
+ 生成粒度约束:
85
+
86
+ - 默认一次只根据一个 `.feature` 文件生成、运行和报告 Playwright 脚本。
87
+ - 当输入是 features 目录时,先列出待处理 `.feature` 文件并选择下一个文件;不要一次性生成整个目录的所有 Playwright 脚本。
88
+ - 用户明确要求“全量生成/全量验收”时,也必须按 feature 文件顺序逐个生成、逐个检查、逐个记录结果;不要在同一次编辑中批量写出所有 spec。
89
+ - 完成一个 feature 文件后,在报告中记录结果和下一个候选 feature 文件,再继续下一个。
90
+
91
+ 混合 validation 输出策略:
92
+
93
+ - 当同一 feature 目录同时包含 `@validation:real-smoke` 和 `@validation:mock-e2e`,按 feature 文件继续拆 spec;如果同一 feature 文件内两类 validation 并存,拆成 `<feature>.real-smoke.spec.ts` 和 `<feature>.mock-e2e.spec.ts`。
94
+ - `real-smoke` spec 不得安装目标业务接口 mock,不得导入 mock data fixture;只允许使用真实页面、真实鉴权和真实后端接口。
95
+ - `mock-e2e` spec 可以使用 `page.route` mock 目标业务接口,用于失败、异常、竞态、边界、特定条件渲染等可控状态。
96
+ - 页面操作 helper 可复用;API mock、mock state、mock data builder 必须只被 `mock-e2e` spec 引用。
97
+ - 报告必须分别统计 `real-smoke` 与 `mock-e2e` 的 selected、automated、passed、mismatch、blocked、manual、gap-pending。
98
+
99
+ ## 工作流
100
+
101
+ 0. **执行前鉴权确认**
102
+
103
+ - 在生成或运行脚本前,先检查项目是否有登录页、路由守卫、鉴权 store、token/cookie、`storageState`、auth helper 或已有登录测试。
104
+ - 必须向用户做一次确认:本次 feature 验收入口是否需要登录或特定权限?
105
+ - 如果需要鉴权,先询问用户采用哪种方式:测试账号登录、已有 `storageState`、登录 helper、seed/session 脚本,或用户指定的其他方式。
106
+ - 未确认鉴权方式前,不要继续生成不可运行的测试脚本。
107
+ - 如果用户确认无需鉴权,在报告中记录 `auth: not required`。
108
+
109
+ 1. **预检**
110
+
111
+ - 识别包管理器、Playwright config、`testDir`、`baseURL` 和可用测试命令。
112
+ - 确认应用能启动或目标 URL 可访问。
113
+ - 确认已按用户指定方式处理鉴权,并确认基础数据足够执行 feature。
114
+ - 如果缺少 `@playwright/test` 或 config,先报告缺失项;只有用户确认后才创建基建或安装依赖。
115
+
116
+ 2. **解析 feature**
117
+
118
+ - 读取 Feature、Rule、Background、Scenario、Scenario Outline、Examples、tags 和原始 steps。
119
+ - 如果输入是 features 目录,按文件名或用户指定顺序选择一个 `.feature` 文件作为当前处理对象;本轮只解析、生成和运行该文件对应的场景。
120
+ - 默认验证用户指定的场景;如果用户指定 `@phase:<id>` 或 `@validation:<type>`,只选择同时满足筛选条件且不含 `@gap-pending` 的 Scenario。
121
+ - 未指定范围时,验证当前 `.feature` 文件内所有不含 `@gap-pending` 且可自动化的 Scenario;不要跨文件扩展范围。
122
+ - 如果用户要求全量 features 目录,仍然按 feature 文件逐个处理,每完成一个文件再进入下一个文件。
123
+ - 保留每个 Scenario 到原始 feature step 的追溯关系。
124
+ - 执行 step coverage review:每个选中 Scenario 的关键 Given/When/Then 必须映射到 Playwright 的前置、动作或断言;不能只因为 Scenario 名称存在就视为覆盖。
125
+ - 如果 feature 明确区分多个交互入口(按钮、Enter、快捷键、菜单等),每个 P0/P1 入口必须有独立动作或断言;缺失时先补脚本或将其标为 blocked/mismatch,不能静默通过。
126
+ - `@validation:real-smoke` 必须不 mock 目标业务接口;如果只是真实页面入口 + mocked 业务接口,应在报告中标明 hybrid 性质,并建议 feature 改为 `mock-e2e` 或 schema 允许的更精确标签。
127
+ - `@validation:real-smoke` 场景如果引用固定业务实体,先验证真实环境是否存在;不存在则标 `blocked`,不能改用 mock 偷跑。
128
+ - 在报告中按 phase 汇总 Scenario 数、验证类型和未选中原因。
129
+ - Phase acceptance gate 下,所有 `@p0` / `@p1` 且 `@validation:mock-e2e` 或 `@validation:real-smoke` 的 Scenario 都必须进入执行计划;仅 `@gap-pending`、`@validation:manual` 或明确无法稳定自动化的 Scenario 可以不生成自动化测试,但必须在报告中标 `blocked` 或 `manual` 并说明原因。
130
+
131
+ 3. **操作真实页面**
132
+
133
+ - 从干净浏览器上下文开始执行,默认复用同一个 `page`。
134
+ - 按 feature 文件中的 Scenario 顺序和 Gherkin step 顺序,在同一个页面上点击、输入、选择、等待和断言。
135
+ - 优先使用稳定 locator:role、label、text、test id;避免随机 class、深层 CSS 和无意义 `nth()`。
136
+ - 每个关键 step 都记录实际 locator、动作、观察到的页面状态和对应断言。
137
+
138
+ 4. **生成 Playwright 脚本**
139
+
140
+ - 使用原生 `@playwright/test`:`test.describe`、`test`、`test.step`、`expect`。
141
+ - Phase 验证模式下,默认只生成当前 phase 的小型 spec,文件名使用 `<phase-id>.validation.spec.ts`,但该 spec 必须覆盖当前 phase 的全部自动化 Scenario;需要 smoke 时使用 `<phase-id>.smoke.spec.ts`,且报告不得把 smoke 标记为 acceptance gate passed。
142
+ - 默认生成一个 `test(...)`,在其中用 `test.step` 按顺序表达 Background、Scenario 和关键 step,避免 Playwright 为每个 Scenario 重开独立上下文。
143
+ - 如果需要更清晰的 Scenario 分段,可以使用 `test.describe.serial` 加共享 `context/page`,但仍应保持一个窗口顺序执行。
144
+ - 只有当场景互相污染、必须验证刷新后的初始状态、权限/数据要求冲突,或单窗口会掩盖真实问题时,才拆成多个独立 `test(...)`;拆分原因必须写入报告。
145
+ - 对写操作只使用可识别的 E2E 测试数据,并记录 cleanup 或兜底清理方式。
146
+ - 对 `real-smoke` 写操作,必须具备用户确认的测试数据范围和 cleanup/rollback 方案;缺少任一条件时标 `blocked`,不要降级成 mock 后继续声称验证真实主链路。
147
+ - 对 `mock-e2e` 场景,mock fixture 应只覆盖选中 Scenario 所需状态;不要为 real-smoke 主流程安装目标业务接口 mock。
148
+ - 对 locator action、navigation 和断言设置显式超时,避免缺失元素拖到整条测试超时;长链路全量验证不应使用无限等待。
149
+ - 对 P0/P1 Scenario 执行断言强度 checklist:请求次数、关键 payload、UI 可见性、消息/行/卡片归属、顺序、负向断言、错误/降级状态至少覆盖适用项;只断言“元素出现”不足以证明归属或竞态安全。
150
+ - 如果 feature 要求“分别对应”“不覆盖”“不污染”“不阻塞”,脚本必须有对应的负向或顺序断言,例如 `toHaveCount`、payload 检查、区域限定 locator、文本顺序检查或旧响应不展示。
151
+ - 人类节奏延迟只作为 headed 演示辅助,不应成为默认验收行为。默认脚本应尽量快速稳定;需要演示时通过环境变量(如 `E2E_HUMAN_ACTION_DELAY_MS`)放慢。
152
+
153
+ 5. **执行并修正测试脚本**
154
+
155
+ - 运行生成的 spec,例如 `pnpm exec playwright test <target-spec>`。
156
+ - 如果失败,先判断是否是 locator、等待、断言表达等测试脚本问题;这类问题应修复后重跑。
157
+ - 不得通过降低业务断言、条件跳过或吞掉失败来制造通过。
158
+
159
+ 6. **判定结果**
160
+ - `passed`:脚本通过,实际页面行为符合 feature。
161
+ - `mismatch`:脚本能稳定复现,但产品行为与 feature 描述不一致;保留失败断言并写入报告。
162
+ - `blocked`:入口、登录、权限、数据、环境或需求歧义导致无法可靠验证;写清缺少什么。
163
+ - `manual`:无法稳定自动化,需要记录人工步骤、证据和接受人;默认不算 passed。
164
+ - `gap-pending`:spec 明确未决的延期场景,必须记录原因和后续任务;P0 不允许该状态。
165
+
166
+ ## 报告要求
167
+
168
+ `validation-report.md` 至少包含:
169
+
170
+ - feature 文件路径和验证范围。
171
+ - 如果是 phase 验证,记录 phase id、validation 类型筛选、选中 Scenario 数、未选中 Scenario 数。
172
+ - 鉴权判断和处理方式:不需要鉴权、测试账号登录、`storageState`、登录 helper、或 blocked 原因。
173
+ - 运行命令、运行时间和运行结果。
174
+ - Scenario 结果表:名称、tags、状态、证据路径、失败原因。
175
+ - Coverage gate:`selected`、`automated`、`passed`、`mismatch`、`blocked`、`manual`、`gap-pending`,并明确 `gate: passed | failed`。
176
+ - Step coverage 摘要:说明关键 Given/When/Then 是否都有动作或断言;如有未覆盖 step,记录原因和处置结果。
177
+ - 断言强度摘要:列出 P0/P1 场景覆盖了哪些关键断言类型(请求次数、payload、UI 归属、顺序、负向断言、错误/降级状态等),并记录接受的残余风险。
178
+ - mismatch 列表:期望、实际、复现步骤、对应断言。
179
+ - blocker 列表:缺失条件、影响的 Scenario、需要用户提供的信息。
180
+ - 生成或修改的 Playwright 脚本路径。
181
+ - 对 `schema: sdd-e2e`,报告必须显式包含 `gate: passed` 或 `gate: failed`,并在最终回复中说明是否已运行 `pnpm sdd:phase <change> <phase>`。
182
+
183
+ 最终回复用户时,简要说明:
184
+
185
+ - 验证了哪些 Scenario。
186
+ - 哪些通过、哪些 mismatch、哪些 blocked。
187
+ - Playwright 脚本和报告路径。
188
+ - 没能验证的原因。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Feature E2E 验收"
3
+ short_description: "先确认鉴权,再按 .feature 单窗口顺序验收"
4
+ default_prompt: "使用 $feature-to-e2e 先确认本次验收是否需要鉴权以及处理方式,再根据 .feature 操作真实页面,尽量在一个窗口上下文中顺序生成并运行 Playwright 脚本,报告实现是否符合功能描述。"
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: openspec-apply-change
3
+ description: 实现一个 OpenSpec 变更中的 tasks。适用于用户想开始实现、继续实现,或逐项完成 tasks 时。
4
+ license: MIT
5
+ compatibility: 需要 openspec CLI。
6
+ metadata:
7
+ author: openspec
8
+ version: "1.0"
9
+ generatedBy: "1.3.1"
10
+ projectOverlay: "sdd-e2e"
11
+ ---
12
+
13
+ 实现一个 OpenSpec 变更中的 tasks。
14
+
15
+ **输入**:可以指定变更名称。如果未指定,先尝试从对话上下文推断;如果含糊或存在歧义,必须让用户从可用变更中选择。
16
+
17
+ **步骤**
18
+
19
+ 1. **选择变更**
20
+
21
+ 如果提供了名称,直接使用。否则:
22
+ - 如果用户在对话中提到过某个变更,尝试从上下文推断
23
+ - 如果只有一个 active change,可以自动选择
24
+ - 如果存在歧义,运行 `openspec list --json` 获取可用变更,并使用 **AskUserQuestion tool** 让用户选择
25
+
26
+ 始终声明:"Using change: <name>",并说明如何覆盖,例如 `/opsx:apply <other>`。
27
+
28
+ 2. **检查状态,理解 schema**
29
+ ```bash
30
+ openspec status --change "<name>" --json
31
+ ```
32
+ 解析 JSON,理解:
33
+ - `schemaName`:当前使用的工作流,例如 `"spec-driven"`
34
+ - 哪个 artifact 包含 tasks(spec-driven 通常是 `"tasks"`,其他 schema 需要看 status)
35
+
36
+ 如果 `openspec/changes/<name>/.openspec.yaml` 声明 `schema: sdd-e2e`,读取 `openspec/schemas/sdd-e2e/schema.yaml`、`openspec/schemas/sdd-e2e.yaml` 和 `openspec/sdd-e2e-flow.md`,并把 features、tasks、phaseReports、finalAcceptance 作为项目级必需契约。
37
+
38
+ 3. **获取 apply 指令**
39
+
40
+ ```bash
41
+ openspec instructions apply --change "<name>" --json
42
+ ```
43
+
44
+ 该命令返回:
45
+ - 上下文文件路径(随 schema 而变,可能是 proposal/specs/design/tasks,也可能是 spec/tests/implementation/docs)
46
+ - 进度(总数、已完成、剩余)
47
+ - task 列表及状态
48
+ - 基于当前状态的动态指令
49
+
50
+ **处理状态:**
51
+ - 如果 `state: "blocked"`(缺少 artifact):展示信息,并建议使用 `openspec-continue-change`
52
+ - 如果 `state: "all_done"`:告知已完成,并建议 archive
53
+ - 否则:进入实现
54
+
55
+ 4. **读取上下文文件**
56
+
57
+ 读取 apply instructions 输出中 `contextFiles` 列出的文件。
58
+ 文件取决于当前 schema:
59
+ - **spec-driven**:proposal、specs、design、tasks
60
+ - 其他 schema:遵循 CLI 输出中的 contextFiles
61
+ - 项目验证扩展:如果变更包含 `specs/**/features/*.feature` 或 `test-cases.md`,即使 OpenSpec schema 没有列出,也要作为验证上下文读取。使用其中的 `@phase:*` 和 `@validation:*` 标签理解 phase 边界和预期验证方式。
62
+ - `schema: sdd-e2e`:必须读取 `openspec/schemas/sdd-e2e/schema.yaml`、`openspec/sdd-e2e-flow.md`、features、`test-cases.md` 和 `tasks.md`;开始实现前先运行 `pnpm sdd:lint-features <change>` 与 `pnpm sdd:lint-tasks <change>`。
63
+ - 修改源码函数、类或方法前,遵守项目 `AGENTS.md`:先做 GitNexus impact analysis,并在高风险时向用户报告后再继续。
64
+
65
+ 5. **展示当前进度**
66
+
67
+ 展示:
68
+ - 当前使用的 schema
69
+ - 进度:`"N/M tasks complete"`
70
+ - 剩余 tasks 概览
71
+ - CLI 返回的动态指令
72
+
73
+ 6. **实现 tasks(循环直到完成或阻塞)**
74
+
75
+ 对每个待办 task:
76
+ - 展示当前正在处理的 task
77
+ - 完成所需代码修改
78
+ - 保持修改最小、聚焦
79
+ - 在 tasks 文件中将 task 标记为完成:`- [ ]` -> `- [x]`
80
+ - 继续下一个 task
81
+
82
+ **Phase 验证扩展:**
83
+ - 如果 `tasks.md` 按 phase 分组,先完成一个 phase 的实现任务,再进入下一个 phase。
84
+ - 如果某个 phase 有类似 "验证 @phase:<id>" 的验证任务,必须为该 phase 调用项目 `feature-to-e2e` 工作流,而不是生成整目录的大范围 E2E。
85
+ - 验证命令和报告只能面向同一个 `@phase:<id>` 且兼容 `@validation:*` 类型的 Scenario。
86
+ - 只有当该 phase 中所有选中的自动化 Scenario 都生成 acceptance report 后,才能把 phase 验证任务标记完成。开发中可以使用 smoke spec,但 smoke 不足以关闭 phase。
87
+ - acceptance report 必须包含 Scenario 覆盖计数。对于 P0/P1 的 `@validation:mock-e2e` 或 `@validation:real-smoke`,覆盖率必须是 100%,除非 Scenario 明确标注为 `@gap-pending`,或带原因标记为 `manual/blocked`。
88
+ - 如果报告包含 `mismatch`、`blocked`、未被产品明确接受的 `manual`,或存在未覆盖的自动化 Scenario,记录结果并暂停。不要通过削弱断言或把 acceptance 降级成 smoke 来标记 phase 完成。
89
+ - 不要仅因为代码 task 完成就把整个 phase 标记完成;phase 完成的条件是实现任务和验证任务都处理完。
90
+ - 对 `schema: sdd-e2e`,每个 phase 验证前后都运行对应 gate:
91
+ - 实现前:`pnpm sdd:lint-features <change>`、`pnpm sdd:lint-tasks <change>`
92
+ - phase 后:`pnpm sdd:phase <change> <phase>`
93
+ - 全部 phase 后:`pnpm sdd:acceptance <change>`
94
+ - `pnpm sdd:phase` 未通过时,不要勾选该 phase 的 Acceptance 验证任务。
95
+ - `pnpm sdd:acceptance` 通过后,才创建或更新 `openspec/changes/<change>/acceptance-coverage.md` 并建议归档。
96
+
97
+ **以下情况需要暂停:**
98
+ - Task 不清楚 -> 询问澄清
99
+ - 实现暴露设计问题 -> 建议更新 artifact
100
+ - 遇到错误或阻塞 -> 报告并等待指导
101
+ - 用户中断
102
+
103
+ 7. **完成或暂停时展示状态**
104
+
105
+ 展示:
106
+ - 本轮完成的 tasks
107
+ - 总进度:`"N/M tasks complete"`
108
+ - 如果全部完成:建议 archive
109
+ - 如果暂停:说明原因并等待指导
110
+
111
+ **实现过程中的输出格式**
112
+
113
+ ```text
114
+ ## 正在实现:<change-name>(schema: <schema-name>)
115
+
116
+ 正在处理 task 3/7:<task description>
117
+ [...正在实现...]
118
+ ✓ Task 已完成
119
+
120
+ 正在处理 task 4/7:<task description>
121
+ [...正在实现...]
122
+ ✓ Task 已完成
123
+ ```
124
+
125
+ **完成时的输出格式**
126
+
127
+ ```text
128
+ ## 实现完成
129
+
130
+ **变更:** <change-name>
131
+ **Schema:** <schema-name>
132
+ **进度:** 7/7 tasks complete ✓
133
+
134
+ ### 本轮完成
135
+ - [x] Task 1
136
+ - [x] Task 2
137
+ ...
138
+
139
+ 所有 tasks 已完成,可以归档该变更。
140
+ ```
141
+
142
+ **暂停时的输出格式(遇到问题)**
143
+
144
+ ```text
145
+ ## 实现已暂停
146
+
147
+ **变更:** <change-name>
148
+ **Schema:** <schema-name>
149
+ **进度:** 4/7 tasks complete
150
+
151
+ ### 遇到的问题
152
+ <问题描述>
153
+
154
+ **选项:**
155
+ 1. <选项 1>
156
+ 2. <选项 2>
157
+ 3. 其他方案
158
+
159
+ 你希望怎么处理?
160
+ ```
161
+
162
+ **约束**
163
+ - 持续推进 tasks,直到完成或被阻塞
164
+ - 开始前必须读取上下文文件(来自 apply instructions 输出)
165
+ - 如果 task 有歧义,实现前暂停并询问
166
+ - 如果实现暴露问题,暂停并建议更新 artifact
167
+ - 代码修改保持最小,并限定在当前 task 范围内
168
+ - 完成每个 task 后立即更新 checkbox
169
+ - 遇到错误、阻塞或需求不清晰时暂停,不要猜测
170
+ - 使用 CLI 输出中的 contextFiles,不要假设固定文件名
171
+ - 对 `schema: sdd-e2e`,不得把 `manual`、`blocked` 或只跑 smoke 的结果当作 phase 完成
172
+ - 对 `schema: sdd-e2e`,不要把 OpenSpec `status.isComplete` 当作实现完成或归档依据;语义完成以 `pnpm sdd:*` gate 为准
173
+
174
+ **流式工作流集成**
175
+
176
+ 该 skill 支持“围绕 change 执行动作”的模型:
177
+
178
+ - **可以随时调用**:可以在所有 artifact 完成前(只要存在 tasks)、部分实现后,或与其他动作交错调用
179
+ - **允许更新 artifact**:如果实现暴露设计问题,建议更新 artifact;不要被 phase 锁死,可以流式推进
180
+ - **允许 phase 验证循环**:如果 phase E2E 暴露 spec 缺口或设计 mismatch,在继续前更新相关 spec/feature/design/task artifact,而不是通过削弱断言强行让测试通过
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: openspec-archive-change
3
+ description: 归档一个已经完成的 OpenSpec 变更。适用于用户想在实现完成后最终收口并归档变更时。
4
+ license: MIT
5
+ compatibility: 需要 openspec CLI。
6
+ metadata:
7
+ author: openspec
8
+ version: "1.0"
9
+ generatedBy: "1.3.1"
10
+ projectOverlay: "sdd-e2e"
11
+ ---
12
+
13
+ 归档实验性工作流中的已完成变更。
14
+
15
+ **输入**:可以指定变更名称。如果未指定,先尝试从对话上下文推断;如果含糊或存在歧义,必须让用户从可用变更中选择。
16
+
17
+ **步骤**
18
+
19
+ 1. **如果未提供变更名称,让用户选择**
20
+
21
+ 运行 `openspec list --json` 获取可用变更。使用 **AskUserQuestion tool** 让用户选择。
22
+
23
+ 只展示 active changes(不包含已归档变更)。
24
+ 如果可用,展示每个变更使用的 schema。
25
+
26
+ **重要**:不要猜测或自动选择变更,始终让用户选择。
27
+
28
+ 2. **检查 artifact 完成状态**
29
+
30
+ 运行 `openspec status --change "<name>" --json` 检查 artifact 完成情况。
31
+
32
+ 解析 JSON,理解:
33
+ - `schemaName`:当前使用的工作流
34
+ - `artifacts`:artifact 列表及其状态(`done` 或其他)
35
+
36
+ **如果有任何 artifact 不是 `done`:**
37
+ - 展示警告,列出未完成 artifact
38
+ - 使用 **AskUserQuestion tool** 确认用户是否仍要继续
39
+ - 用户确认后继续
40
+
41
+ 3. **检查 task 完成状态**
42
+
43
+ 读取 tasks 文件(通常是 `tasks.md`),检查是否存在未完成任务。
44
+
45
+ 统计 `- [ ]`(未完成)和 `- [x]`(已完成)的 task 数量。
46
+
47
+ **如果发现未完成 tasks:**
48
+ - 展示警告,说明未完成数量
49
+ - 使用 **AskUserQuestion tool** 确认用户是否仍要继续
50
+ - 用户确认后继续
51
+
52
+ **如果不存在 tasks 文件**:跳过 task 相关警告并继续。
53
+
54
+ 4. **检查 SDD-E2E final acceptance**
55
+
56
+ 如果 `openspec/changes/<name>/.openspec.yaml` 声明 `schema: sdd-e2e`:
57
+
58
+ - 读取 `openspec/schemas/sdd-e2e/schema.yaml`、`openspec/schemas/sdd-e2e.yaml` 和 `openspec/sdd-e2e-flow.md` 作为项目级归档规则。
59
+ - 先运行:
60
+ ```bash
61
+ pnpm sdd:acceptance <name>
62
+ ```
63
+ - 检查 `openspec/changes/<name>/acceptance-coverage.md` 是否存在,且 final acceptance 包含 `Final gate: passed` 或等价的 passed 结论。
64
+ - 如果 final acceptance 未通过,停止归档并展示失败原因。只有当用户明确要求“带例外归档”时,才允许继续,并在摘要中记录该例外。
65
+
66
+ **重要**:`schema: sdd-e2e` 的 change 不能因为 tasks 勾选完成就默认可归档;final acceptance 是归档前质量门禁。
67
+
68
+ 5. **执行 Spec Impact Review**
69
+
70
+ 归档前必须检查本次 change 是否影响已有主 spec 的代码范围:
71
+
72
+ - 确定归档比较基线:默认使用 `master`;如果 change、PR 或仓库约定明确使用其他目标分支,则使用该目标分支。
73
+ - 在网络和权限允许时,先执行 `git fetch origin <base_ref>`,保证本地比较基线尽量接近远端最新状态。
74
+ - 优先运行 `gitnexus_detect_changes(scope: "compare", base_ref: <base_ref>)`,获取本次 change 相对归档基线影响的 symbols、files、processes 和 APIs。
75
+ - 如果 GitNexus compare 不可用,降级运行 `gitnexus_detect_changes(scope: "all")`,并在归档摘要中记录降级原因。
76
+ - 读取所有 `openspec/specs/*/spec.md` 中的 `## Code Scope` 区块。
77
+ - 比较本次改动范围与已有主 spec 的 `Code Scope` 是否重合。
78
+
79
+ **如果存在重合:**
80
+ - 在继续归档前展示重合项,包括 spec、files、processes 或 APIs。
81
+ - 必须记录处理结论,且结论必须属于以下之一:
82
+ - 已同步更新相关主 spec
83
+ - 行为未变化,不需要更新
84
+ - 仅实现细节重合
85
+ - 需要后续补充 spec gap
86
+ - 不允许在存在重合时静默归档。
87
+
88
+ **如果无法运行 GitNexus:**
89
+ - 优先使用 `git diff --name-only <base_ref>...HEAD` 作为降级检查。
90
+ - 如果无法确定或读取 `<base_ref>`,合并 `git diff --name-only` 与 `git diff --name-only --cached` 的结果作为工作区降级检查。
91
+ - 在归档摘要中记录降级原因和检查结论。
92
+
93
+ 6. **评估 delta spec 同步状态**
94
+
95
+ 检查 `openspec/changes/<name>/specs/` 下是否存在 delta specs。如果不存在,跳过同步提示。
96
+
97
+ **如果存在 delta specs:**
98
+ - 将每个 delta spec 与对应主 spec `openspec/specs/<capability>/spec.md` 比较
99
+ - 判断会应用哪些变化(新增、修改、删除、重命名)
100
+ - 在询问用户前,展示合并后的摘要
101
+
102
+ **提示选项:**
103
+ - 如果需要同步:"Sync now (recommended)"、"Archive without syncing"
104
+ - 如果已经同步:"Archive now"、"Sync anyway"、"Cancel"
105
+
106
+ 如果用户选择同步,使用 Task tool(`subagent_type: "general-purpose"`,prompt: `"Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"`)。无论是否同步,随后继续归档。
107
+
108
+ 7. **执行归档**
109
+
110
+ 如果 archive 目录不存在,先创建:
111
+ ```bash
112
+ mkdir -p openspec/changes/archive
113
+ ```
114
+
115
+ 使用当前日期生成目标名称:`YYYY-MM-DD-<change-name>`
116
+
117
+ **检查目标是否已存在:**
118
+ - 如果存在:报错,并建议重命名已有 archive 或使用不同日期
119
+ - 如果不存在:移动 change 目录到 archive
120
+
121
+ ```bash
122
+ mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>
123
+ ```
124
+
125
+ 8. **展示摘要**
126
+
127
+ 展示归档完成摘要,包括:
128
+ - 变更名称
129
+ - 使用的 schema
130
+ - 归档位置
131
+ - specs 是否已同步(如适用)
132
+ - Spec Impact Review 结论
133
+ - 关于任何警告的说明(artifact/tasks 未完成等)
134
+
135
+ **成功输出格式**
136
+
137
+ ```text
138
+ ## 归档完成
139
+
140
+ **变更:** <change-name>
141
+ **Schema:** <schema-name>
142
+ **归档到:** openspec/changes/archive/YYYY-MM-DD-<name>/
143
+ **Specs:** ✓ 已同步到主 specs(或 "No delta specs" / "Sync skipped")
144
+
145
+ 所有 artifacts 已完成。所有 tasks 已完成。
146
+ ```
147
+
148
+ **约束**
149
+ - 未提供变更名称时,必须让用户选择
150
+ - 使用 artifact graph(`openspec status --json`)检查完成状态
151
+ - 不要因为警告而阻止归档;告知并确认即可
152
+ - 移动归档时保留 `.openspec.yaml`(目录整体移动即可)
153
+ - 清晰展示发生了什么
154
+ - 如果用户请求同步,使用 openspec-sync-specs 的 agent-driven 方式
155
+ - 如果存在 delta specs,始终先做同步评估,并在询问用户前展示合并摘要
156
+ - 归档前必须执行 Spec Impact Review;如果改动范围与已有主 spec 的 Code Scope 重合,必须记录处理结论
157
+ - 对 `schema: sdd-e2e`,OpenSpec artifact 完成状态不是归档放行条件;`pnpm sdd:acceptance` 才是最终 gate