@gordon.gan/specflow 1.0.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.
- package/LICENSE +31 -0
- package/README.md +442 -0
- package/bin/specflow.js +2 -0
- package/dist/cli/commands/change-archive.d.ts +26 -0
- package/dist/cli/commands/change-archive.js +50 -0
- package/dist/cli/commands/change-new.d.ts +18 -0
- package/dist/cli/commands/change-new.js +53 -0
- package/dist/cli/commands/change-phase.d.ts +33 -0
- package/dist/cli/commands/change-phase.js +66 -0
- package/dist/cli/commands/change-status.d.ts +35 -0
- package/dist/cli/commands/change-status.js +95 -0
- package/dist/cli/commands/doctor.d.ts +9 -0
- package/dist/cli/commands/doctor.js +48 -0
- package/dist/cli/commands/init.d.ts +16 -0
- package/dist/cli/commands/init.js +122 -0
- package/dist/cli/commands/instructions.d.ts +21 -0
- package/dist/cli/commands/instructions.js +75 -0
- package/dist/cli/commands/parity-report.d.ts +10 -0
- package/dist/cli/commands/parity-report.js +67 -0
- package/dist/cli/commands/sync.d.ts +4 -0
- package/dist/cli/commands/sync.js +40 -0
- package/dist/cli/commands/validate.d.ts +21 -0
- package/dist/cli/commands/validate.js +46 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +52 -0
- package/dist/core/archive.d.ts +39 -0
- package/dist/core/archive.js +154 -0
- package/dist/core/artifact-graph/graph.d.ts +60 -0
- package/dist/core/artifact-graph/graph.js +141 -0
- package/dist/core/artifact-graph/index.d.ts +10 -0
- package/dist/core/artifact-graph/index.js +7 -0
- package/dist/core/artifact-graph/instruction-loader.d.ts +45 -0
- package/dist/core/artifact-graph/instruction-loader.js +37 -0
- package/dist/core/artifact-graph/outputs.d.ts +35 -0
- package/dist/core/artifact-graph/outputs.js +48 -0
- package/dist/core/artifact-graph/resolver.d.ts +54 -0
- package/dist/core/artifact-graph/resolver.js +139 -0
- package/dist/core/artifact-graph/schema.d.ts +23 -0
- package/dist/core/artifact-graph/schema.js +115 -0
- package/dist/core/artifact-graph/state.d.ts +9 -0
- package/dist/core/artifact-graph/state.js +93 -0
- package/dist/core/artifact-graph/types.d.ts +123 -0
- package/dist/core/artifact-graph/types.js +29 -0
- package/dist/core/parsers/change-parser.d.ts +20 -0
- package/dist/core/parsers/change-parser.js +22 -0
- package/dist/core/parsers/index.d.ts +7 -0
- package/dist/core/parsers/index.js +4 -0
- package/dist/core/parsers/markdown-parser.d.ts +35 -0
- package/dist/core/parsers/markdown-parser.js +193 -0
- package/dist/core/parsers/requirement-blocks.d.ts +21 -0
- package/dist/core/parsers/requirement-blocks.js +57 -0
- package/dist/core/parsers/spec-structure.d.ts +22 -0
- package/dist/core/parsers/spec-structure.js +105 -0
- package/dist/core/specs-apply.d.ts +22 -0
- package/dist/core/specs-apply.js +165 -0
- package/dist/core/templates/index.d.ts +31 -0
- package/dist/core/templates/index.js +80 -0
- package/dist/core/templates/types.d.ts +4 -0
- package/dist/core/templates/types.js +1 -0
- package/dist/core/validation/constants.d.ts +14 -0
- package/dist/core/validation/constants.js +14 -0
- package/dist/core/validation/types.d.ts +13 -0
- package/dist/core/validation/types.js +6 -0
- package/dist/core/validation/validator.d.ts +24 -0
- package/dist/core/validation/validator.js +250 -0
- package/dist/integrations/claude/adapter.d.ts +2 -0
- package/dist/integrations/claude/adapter.js +106 -0
- package/dist/integrations/codex/adapter.d.ts +2 -0
- package/dist/integrations/codex/adapter.js +141 -0
- package/dist/integrations/cursor/adapter.d.ts +2 -0
- package/dist/integrations/cursor/adapter.js +126 -0
- package/dist/integrations/shared/adapter-registry.d.ts +4 -0
- package/dist/integrations/shared/adapter-registry.js +27 -0
- package/dist/integrations/shared/asset-copy.d.ts +2 -0
- package/dist/integrations/shared/asset-copy.js +44 -0
- package/dist/integrations/shared/asset-hash.d.ts +4 -0
- package/dist/integrations/shared/asset-hash.js +54 -0
- package/dist/integrations/shared/capability-evidence.d.ts +1 -0
- package/dist/integrations/shared/capability-evidence.js +42 -0
- package/dist/integrations/shared/command-catalog.d.ts +6 -0
- package/dist/integrations/shared/command-catalog.js +13 -0
- package/dist/integrations/shared/managed-assets.d.ts +2 -0
- package/dist/integrations/shared/managed-assets.js +21 -0
- package/dist/integrations/shared/marker-write.d.ts +3 -0
- package/dist/integrations/shared/marker-write.js +48 -0
- package/dist/integrations/shared/migration-state.d.ts +2 -0
- package/dist/integrations/shared/migration-state.js +67 -0
- package/dist/integrations/shared/parity-comparator.d.ts +6 -0
- package/dist/integrations/shared/parity-comparator.js +97 -0
- package/dist/integrations/shared/parity-manifest.d.ts +13 -0
- package/dist/integrations/shared/parity-manifest.js +58 -0
- package/dist/integrations/shared/runtime-assets.d.ts +2 -0
- package/dist/integrations/shared/runtime-assets.js +21 -0
- package/dist/integrations/shared/skill-renderer.d.ts +5 -0
- package/dist/integrations/shared/skill-renderer.js +77 -0
- package/dist/integrations/shared/types.d.ts +35 -0
- package/dist/integrations/shared/types.js +1 -0
- package/dist/utils/change-metadata.d.ts +38 -0
- package/dist/utils/change-metadata.js +82 -0
- package/dist/utils/change-utils.d.ts +53 -0
- package/dist/utils/change-utils.js +97 -0
- package/dist/utils/file-system.d.ts +35 -0
- package/dist/utils/file-system.js +67 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/project-root.d.ts +22 -0
- package/dist/utils/project-root.js +44 -0
- package/dist/utils/task-progress.d.ts +39 -0
- package/dist/utils/task-progress.js +62 -0
- package/package.json +72 -0
- package/prompts/build/ecc-go-reviewer.md +80 -0
- package/prompts/build/ecc-java-reviewer.md +185 -0
- package/prompts/build/ecc-kotlin-reviewer.md +163 -0
- package/prompts/build/ecc-python-reviewer.md +102 -0
- package/prompts/build/ecc-rust-reviewer.md +98 -0
- package/prompts/build/ecc-typescript-reviewer.md +116 -0
- package/prompts/build/language-router.md +22 -0
- package/prompts/build/phase-a-plan.md +288 -0
- package/prompts/build/phase-b-execute.md +276 -0
- package/prompts/build/phase-b-review.md +119 -0
- package/prompts/build/phase-b-worktree.md +215 -0
- package/prompts/build/plan-document-reviewer.md +51 -0
- package/prompts/build/tdd.md +184 -0
- package/prompts/done/branch-finish.md +204 -0
- package/prompts/fix/debug.md +249 -0
- package/prompts/plan/design-draft.md +123 -0
- package/prompts/plan/proposal.md +85 -0
- package/prompts/plan/specs.md +114 -0
- package/prompts/plan/tasks-draft.md +123 -0
- package/prompts/reference/openspec/apply-instruction.md +2 -0
- package/prompts/reference/openspec/design-instruction.md +20 -0
- package/prompts/reference/openspec/proposal-instruction.md +18 -0
- package/prompts/reference/openspec/specs-instruction.md +47 -0
- package/prompts/reference/openspec/tasks-instruction.md +26 -0
- package/prompts/reference/specflow/example-design.md +284 -0
- package/prompts/reference/superpowers/anthropic-best-practices.md +1150 -0
- package/prompts/reference/superpowers/codex-tools.md +29 -0
- package/prompts/reference/superpowers/condition-based-waiting-example.ts +158 -0
- package/prompts/reference/superpowers/condition-based-waiting.md +115 -0
- package/prompts/reference/superpowers/defense-in-depth.md +122 -0
- package/prompts/reference/superpowers/find-polluter.sh +63 -0
- package/prompts/reference/superpowers/graphviz-conventions.dot +172 -0
- package/prompts/reference/superpowers/persuasion-principles.md +187 -0
- package/prompts/reference/superpowers/root-cause-tracing.md +169 -0
- package/prompts/reference/superpowers/testing-anti-patterns.md +299 -0
- package/prompts/reference/superpowers/testing-skills-with-subagents.md +384 -0
- package/prompts/reference/superpowers/using-superpowers.md +117 -0
- package/prompts/reference/superpowers/writing-skills.md +655 -0
- package/prompts/refine/brainstorm.md +241 -0
- package/prompts/refine/design-output.md +126 -0
- package/prompts/refine/spec-document-reviewer.md +51 -0
- package/prompts/refine/update-artifacts.md +185 -0
- package/prompts/review/code-review.md +223 -0
- package/prompts/shared/code-reviewer-prompt.md +98 -0
- package/prompts/shared/dispatching-parallel-agents.md +143 -0
- package/prompts/shared/executing-plans.md +67 -0
- package/prompts/shared/implementer-prompt.md +115 -0
- package/prompts/shared/receiving-code-review.md +174 -0
- package/prompts/shared/spec-reviewer-prompt.md +63 -0
- package/prompts/test/tdd.md +236 -0
- package/prompts/test/verification.md +129 -0
- package/prompts/verify/ecc-security-reviewer.md +112 -0
- package/prompts/verify/verification.md +196 -0
- package/schemas/specflow/schema.yaml +48 -0
- package/skills/specflow-build/SKILL.md +129 -0
- package/skills/specflow-done/SKILL.md +68 -0
- package/skills/specflow-fix/SKILL.md +74 -0
- package/skills/specflow-plan/SKILL.md +82 -0
- package/skills/specflow-refine/SKILL.md +128 -0
- package/skills/specflow-review/SKILL.md +40 -0
- package/skills/specflow-scan/SKILL.md +48 -0
- package/skills/specflow-snap/SKILL.md +46 -0
- package/skills/specflow-test/SKILL.md +48 -0
- package/skills/specflow-verify/SKILL.md +77 -0
- package/templates/design.md +19 -0
- package/templates/proposal.md +23 -0
- package/templates/spec.md +42 -0
- package/templates/tasks.md +9 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 bstzyf
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
This package incorporates content derived from the following MIT-licensed projects:
|
|
26
|
+
|
|
27
|
+
- OpenSpec (https://github.com/Fission-AI/OpenSpec) — Copyright (c) Fission-AI
|
|
28
|
+
- Superpowers (https://github.com/obra/superpowers) — Copyright (c) Jesse Vincent
|
|
29
|
+
|
|
30
|
+
Portions of this codebase were adapted and rewritten from those projects.
|
|
31
|
+
See `<!-- SOURCE: ... -->` comments in prompt files for specific attribution.
|
package/README.md
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
# SpecFlow
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/specflow)
|
|
4
|
+
[](https://www.npmjs.com/package/specflow)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
**一句话:plan 想清楚,refine 打磨透,build 做到位,done 归档好。**
|
|
8
|
+
|
|
9
|
+
> Cursor 用户可直接参考:`CURSOR_PACKAGING_AND_USAGE_GUIDE.md`
|
|
10
|
+
> Codex 用户可直接参考:`CODEX_PACKAGING_AND_USAGE_GUIDE.md`
|
|
11
|
+
|
|
12
|
+
SpecFlow 把两个开源框架合并成一个工具:
|
|
13
|
+
- **OpenSpec** — 结构化需求规划(proposal → specs → design → tasks)
|
|
14
|
+
- **Superpowers** — 工程执行纪律(TDD、系统化调试、代码审查、subagent 编排)
|
|
15
|
+
|
|
16
|
+
一个 CLI + 一套跨 IDE 工作流技能(Claude Code / Cursor / Codex),覆盖从「扫描代码库」到「归档上线」的完整开发生命周期。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 前置依赖
|
|
21
|
+
|
|
22
|
+
- **Node.js ≥ 20.19.0**(`node --version` 检查)
|
|
23
|
+
- **Git**(用于 build 的 worktree 和 done 的分支管理)
|
|
24
|
+
- **AI 编码环境(任选其一或组合)**
|
|
25
|
+
- **Claude Code** — `/specflow:*` 斜杠命令
|
|
26
|
+
- **Cursor** — `specflow:*` 命令(见 Cursor 指南)
|
|
27
|
+
- **OpenAI Codex** — `$specflow-*` 技能(见 Codex 指南)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 安装
|
|
32
|
+
|
|
33
|
+
### 方式 1:从 npm 全局安装(推荐,发布后可用)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g specflow
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 方式 2:从 GitHub 直接安装(发布前/最新代码)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install -g github:Gordon-Gan-Jiang/specflow
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 方式 3:本地源码安装(开发者 / 贡献者)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/Gordon-Gan-Jiang/specflow.git
|
|
49
|
+
cd specflow
|
|
50
|
+
npm install
|
|
51
|
+
npm run build
|
|
52
|
+
npm link
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
使用 `npm link` 后,在源码里改代码 → 重新 `npm run build` → 全局的 `specflow` 命令立即生效(符号链接)。
|
|
56
|
+
|
|
57
|
+
### 方式 4:通过本地 tarball 分发
|
|
58
|
+
|
|
59
|
+
在有源码的机器上打包:
|
|
60
|
+
```bash
|
|
61
|
+
npm run build
|
|
62
|
+
npm pack # 生成 specflow-0.2.2.tgz
|
|
63
|
+
```
|
|
64
|
+
在目标机器上安装:
|
|
65
|
+
```bash
|
|
66
|
+
npm install -g ./specflow-0.2.2.tgz
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 验证安装
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
specflow --version # 应输出 0.2.2
|
|
73
|
+
specflow --help
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 卸载
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm uninstall -g specflow
|
|
80
|
+
# 如果用的是 npm link:
|
|
81
|
+
npm unlink -g specflow
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 在项目中使用
|
|
87
|
+
|
|
88
|
+
### 初始化(每个项目一次)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
cd your-project
|
|
92
|
+
specflow init # 默认:Claude + Cursor(--ide both)
|
|
93
|
+
specflow init --ide codex # 仅 Codex
|
|
94
|
+
specflow init --ide all # Claude + Cursor + Codex
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
这一步会:
|
|
98
|
+
- 创建 `specflow/` 目录(存放 specs 和 changes)
|
|
99
|
+
- 写入 `specflow/config.yaml`(项目上下文)
|
|
100
|
+
- 按 `--ide` 生成对应托管资产:
|
|
101
|
+
- **Claude**:`.claude/skills/`、`.claude/commands/specflow/`、`.claude/specflow/`
|
|
102
|
+
- **Cursor**:`.cursor/skills/`、`.cursor/commands/specflow/`、`.cursor/rules/`、`.cursor/specflow/`
|
|
103
|
+
- **Codex**:`.agents/skills/`、`.agents/specflow/`、`AGENTS.md` 上下文块
|
|
104
|
+
- **自动追加** `.gitignore`,忽略可再生的 prompts/schemas/templates(幂等,不覆盖已有内容)
|
|
105
|
+
|
|
106
|
+
init 后:
|
|
107
|
+
- Claude Code:斜杠命令 `/specflow:*` 立即可用
|
|
108
|
+
- Cursor:命令 `specflow:*` 立即可用
|
|
109
|
+
- Codex:技能 `$specflow-*` 立即可用
|
|
110
|
+
|
|
111
|
+
### 重新初始化
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# 删掉后重新跑 init
|
|
115
|
+
rm -rf specflow/config.yaml .claude/specflow/
|
|
116
|
+
specflow init
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
(init 检测到已初始化会拒绝运行,避免误覆盖)
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 核心流程
|
|
124
|
+
|
|
125
|
+
**每阶段深度思考 → 多轮迭代精化**:每个阶段一次性产出实质内容(非占位骨架),再通过内部多轮迭代把 artifact 精化到稳态,最后进入执行。
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
/specflow:scan [规划中 · v0.3] 扫描已有代码生成 specs 基线;当前请直接用 /specflow:plan 描述已有行为
|
|
129
|
+
↓
|
|
130
|
+
/specflow:plan 一次产出 4 个 artifact:proposal + delta specs + design + tasks(first-iteration 深度思考,非纯骨架)
|
|
131
|
+
↓
|
|
132
|
+
/specflow:refine 内部多轮精化循环(≥2 rounds,AI 收敛判定,不设上限)
|
|
133
|
+
每轮攻击性审查 + 4 个挑战行为:
|
|
134
|
+
· 挑战假设 · 提新 options
|
|
135
|
+
· 探边界 · 质疑 scope
|
|
136
|
+
可更新任意 artifact(proposal / specs / design / tasks)
|
|
137
|
+
↓
|
|
138
|
+
/specflow:build Phase A:基于 refine 稳定后的 artifact,用 writing-plans 严格精化(rewrite)tasks.md
|
|
139
|
+
Phase B:逐任务 TDD 执行(subagent 模式)
|
|
140
|
+
design 有漏即停,回 refine 补齐
|
|
141
|
+
↓
|
|
142
|
+
/specflow:review 代码审查(对照 specs 检查回归)
|
|
143
|
+
↓
|
|
144
|
+
/specflow:test 全量测试(单元 + 集成 + E2E + 回归)
|
|
145
|
+
↓
|
|
146
|
+
/specflow:verify 双重校验(delta specs 验收 + 主 specs 回归)
|
|
147
|
+
↓
|
|
148
|
+
/specflow:done 归档变更 → specs 合并 → git 分支清理
|
|
149
|
+
默认要求 phase=built,可用 --force 跳过
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
另外两个快捷命令:
|
|
153
|
+
```
|
|
154
|
+
/specflow:fix 修 Bug 一条龙(调试 → TDD 修复 → 自动归档)
|
|
155
|
+
/specflow:snap 事后补档(从 git diff 反推变更记录)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 新机制(v0.2.0)
|
|
159
|
+
|
|
160
|
+
- **plan 一次产出 4 artifact**:proposal、delta specs、design、tasks 同步生成,每个都是实质的"第一轮深度思考"(first-iteration),不再是占位骨架
|
|
161
|
+
- **refine 内部多轮循环**:至少 2 轮,AI 语义判断收敛,不设上限;每轮显式执行 4 个挑战行为(挑战假设 / 提新 options / 探边界 / 质疑 scope);可更新任意 artifact
|
|
162
|
+
- **build Phase A 改为 rewrite**:不再是"生成" tasks.md,而是基于 refine 稳定后的 artifact 用 Superpowers writing-plans 严格规则"精化"重写;发现 design 缺漏即停并回 refine
|
|
163
|
+
- **`.specflow.yaml` 新增 `phase` 字段**:追踪变更生命周期(`plan` / `refined` / `built` / `archived`);`specflow change archive` 默认要求 `phase=built`,可用 `--force` 跳过守门
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 快速上手示例
|
|
168
|
+
|
|
169
|
+
### 5 分钟跑通全流程
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# 1. 安装(任选一种)
|
|
173
|
+
npm install -g specflow
|
|
174
|
+
|
|
175
|
+
# 2. 进入你的项目
|
|
176
|
+
cd my-project
|
|
177
|
+
|
|
178
|
+
# 3. 初始化
|
|
179
|
+
specflow init
|
|
180
|
+
|
|
181
|
+
# 4. 打开 Claude Code,在会话里输入:
|
|
182
|
+
/specflow:plan "给用户管理模块加个批量导入功能"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Claude Code 接下来会:
|
|
186
|
+
1. 读 `.claude/skills/specflow-plan/SKILL.md` 编排器
|
|
187
|
+
2. 问你几个澄清问题(一次一个)
|
|
188
|
+
3. 生成 `specflow/changes/bulk-import/proposal.md`
|
|
189
|
+
4. 展示 proposal 等你**确认**
|
|
190
|
+
5. 确认后生成 delta specs `specs/*/spec.md`
|
|
191
|
+
6. 提示你下一步是 `/specflow:refine`
|
|
192
|
+
|
|
193
|
+
### 更完整的示例(4 个场景)
|
|
194
|
+
|
|
195
|
+
#### 场景 1:新项目从零开始
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
/specflow:plan "添加用户注册和登录功能"
|
|
199
|
+
/specflow:refine # 讨论技术方案,输出 design.md
|
|
200
|
+
/specflow:build # TDD 实现,每任务用户确认
|
|
201
|
+
/specflow:review # 代码审查
|
|
202
|
+
/specflow:test # 跑测试
|
|
203
|
+
/specflow:verify # 对照 specs 验收
|
|
204
|
+
/specflow:done # 归档 + merge
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### 场景 2:接手已有项目(v0.2.x 工作流)
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
cd legacy-project
|
|
211
|
+
specflow init
|
|
212
|
+
|
|
213
|
+
# 在 Claude Code 里:
|
|
214
|
+
# 注意:/specflow:scan 当前规划在 v0.3,未实现。
|
|
215
|
+
# v0.2.x 的推荐做法是直接进 plan,在 proposal Q&A 里描述已有行为 +
|
|
216
|
+
# 新增变更,让 plan 为将要改动的 capability 生成 delta spec 基线。
|
|
217
|
+
/specflow:plan "描述已有行为 + 你这次要改的新功能"
|
|
218
|
+
/specflow:refine # 对 plan 产出做 ≥2 轮攻击性审查
|
|
219
|
+
/specflow:build # Phase A 重写 tasks.md → Phase B TDD
|
|
220
|
+
/specflow:done # 归档,delta spec 合入主 specs/
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### 场景 3:紧急修 Bug
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
/specflow:fix "登录接口在 token 过期时返回 500 而不是 401"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
一条命令包含:
|
|
230
|
+
1. 自动创建轻量变更
|
|
231
|
+
2. 定位相关 specs(对照规格理解预期行为)
|
|
232
|
+
3. 系统化调试(4 步法:调查 → 模式 → 假设 → 验证)
|
|
233
|
+
4. TDD 修复(先写复现测试让它红,再修代码让它绿)
|
|
234
|
+
5. 自动代码审查
|
|
235
|
+
6. 跑测试
|
|
236
|
+
7. 归档
|
|
237
|
+
|
|
238
|
+
紧急模式跳过审查:
|
|
239
|
+
```
|
|
240
|
+
/specflow:fix --urgent "生产环境崩溃"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
#### 场景 4:同事改了代码没走流程,事后补档
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
/specflow:snap "重构了认证模块"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
分析 git diff + git log,反推完整变更记录,推断受影响的 specs,用户确认后自动归档。
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 命令速查
|
|
254
|
+
|
|
255
|
+
### Claude Code 技能命令(在 Claude Code 会话里用)
|
|
256
|
+
|
|
257
|
+
| 命令 | 说明 |
|
|
258
|
+
|---|---|
|
|
259
|
+
| `/specflow:scan` | **[规划中 · v0.3]** 扫描已有代码库生成 specs 基线;v0.2.x 未实现,触发时 skill 会提示替代方案 |
|
|
260
|
+
| `/specflow:plan` | 需求规划:生成 proposal + delta specs |
|
|
261
|
+
| `/specflow:refine` | 技术方案探讨(brainstorming + design.md) |
|
|
262
|
+
| `/specflow:build` | 两阶段构建:生成计划 → subagent TDD 执行 |
|
|
263
|
+
| `/specflow:review` | 代码审查(含 specs 回归检查) |
|
|
264
|
+
| `/specflow:test` | 全量测试 + 验证(单元/集成/E2E/回归) |
|
|
265
|
+
| `/specflow:verify` | 双重校验:delta specs 验收 + 主 specs 回归 |
|
|
266
|
+
| `/specflow:done` | 归档变更 + specs 合并 + git 分支清理 |
|
|
267
|
+
| `/specflow:fix` | 修 Bug 快速通道(调试 → TDD → 归档) |
|
|
268
|
+
| `/specflow:snap` | 事后补档(从 git diff 反推变更记录) |
|
|
269
|
+
|
|
270
|
+
### CLI 命令(在终端里用)
|
|
271
|
+
|
|
272
|
+
| 命令 | 说明 |
|
|
273
|
+
|---|---|
|
|
274
|
+
| `specflow init` | 初始化项目(生成目录、技能、prompts) |
|
|
275
|
+
| `specflow change new <名称>` | 创建新的变更 |
|
|
276
|
+
| `specflow change status <名称>` | 查看变更的 artifact 完成状态 |
|
|
277
|
+
| `specflow change archive <名称>` | 归档变更(delta merge + 移入 archive) |
|
|
278
|
+
| `specflow validate <文件>` | 校验 spec 文件格式 |
|
|
279
|
+
| `specflow instructions <artifact> <change>` | 查看某个 artifact 的创建指令 |
|
|
280
|
+
|
|
281
|
+
CLI 命令会从当前目录**向上查找**项目根(找 `specflow/config.yaml`),类似 `git` 的行为。在项目任意子目录下运行都能工作。
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 架构
|
|
286
|
+
|
|
287
|
+
SpecFlow 分三层,各司其职:
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
┌─────────────────────────────────────────────────┐
|
|
291
|
+
│ CLI 层(确定性逻辑) │
|
|
292
|
+
│ TypeScript 实现。负责文件操作、specs 校验、 │
|
|
293
|
+
│ artifact 状态追踪、delta merge、归档。 │
|
|
294
|
+
│ 不涉及任何 AI 逻辑。 │
|
|
295
|
+
├─────────────────────────────────────────────────┤
|
|
296
|
+
│ SKILL.md 层(编排层) │
|
|
297
|
+
│ 每个命令一个 SKILL.md(50-100 行)。 │
|
|
298
|
+
│ 定义工作流阶段、hard gate 门禁、用户确认点。 │
|
|
299
|
+
│ 通过 Read 指令按需加载 prompt 文件。 │
|
|
300
|
+
├─────────────────────────────────────────────────┤
|
|
301
|
+
│ Prompts 层(执行指令) │
|
|
302
|
+
│ 详细的指令文件,告诉 Claude Code 在每个阶段 │
|
|
303
|
+
│ 具体怎么做:写 proposal、做 brainstorming、 │
|
|
304
|
+
│ 执行 TDD、做 code review 等。 │
|
|
305
|
+
│ 按需加载,不会一次全部塞进 context。 │
|
|
306
|
+
└─────────────────────────────────────────────────┘
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**为什么这样设计?**
|
|
310
|
+
|
|
311
|
+
- **渐进加载**:一个 SKILL.md 如果把所有 prompt 内嵌进去会超过 1000 行,Claude Code 容易"迷路"。拆成小文件按阶段加载,每个阶段的指令清晰聚焦。
|
|
312
|
+
- **Hard Gate 双重保障**:关键门禁(如"设计未确认不许写代码")在 SKILL.md 编排层和 prompt 文件两处都声明,防止执行漂移。
|
|
313
|
+
- **CLI 处理确定性操作**:delta specs 合并、格式校验等需要精确文本操作的工作由 TypeScript 代码执行,不靠 AI 猜。
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## 关键概念
|
|
318
|
+
|
|
319
|
+
### Specs(规格文件)
|
|
320
|
+
|
|
321
|
+
存放在 `specflow/specs/` 目录,是项目的 **Source of Truth(唯一事实来源)**。
|
|
322
|
+
|
|
323
|
+
每个 spec 文件描述一个功能模块的行为规格:
|
|
324
|
+
|
|
325
|
+
```markdown
|
|
326
|
+
### Requirement: 用户登录
|
|
327
|
+
系统应当支持通过邮箱和密码进行用户认证。
|
|
328
|
+
|
|
329
|
+
#### Scenario: 登录成功
|
|
330
|
+
- **WHEN** 用户提交有效凭据
|
|
331
|
+
- **THEN** 系统返回认证 token
|
|
332
|
+
|
|
333
|
+
#### Scenario: 登录失败
|
|
334
|
+
- **WHEN** 用户提交错误密码
|
|
335
|
+
- **THEN** 系统返回 401 错误
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Changes(变更记录)
|
|
339
|
+
|
|
340
|
+
存放在 `specflow/changes/` 目录。每次新功能或修复都是一个 change。
|
|
341
|
+
|
|
342
|
+
一个 change 包含:
|
|
343
|
+
- `proposal.md` — 为什么做、做什么
|
|
344
|
+
- `specs/` — delta specs(ADDED/MODIFIED/REMOVED/RENAMED 的需求变更)
|
|
345
|
+
- `design.md` — 技术方案
|
|
346
|
+
- `tasks.md` — 实施任务清单(带 checkbox)
|
|
347
|
+
|
|
348
|
+
归档时,delta specs 会自动合并到主 specs,change 移入 `specflow/changes/archive/`。
|
|
349
|
+
|
|
350
|
+
### Delta Specs(增量规格)
|
|
351
|
+
|
|
352
|
+
描述对现有 specs 的变更,支持四种操作:
|
|
353
|
+
|
|
354
|
+
```markdown
|
|
355
|
+
## ADDED Requirements
|
|
356
|
+
(新增的需求)
|
|
357
|
+
|
|
358
|
+
## MODIFIED Requirements
|
|
359
|
+
(修改的需求 — 必须包含完整更新内容)
|
|
360
|
+
|
|
361
|
+
## REMOVED Requirements
|
|
362
|
+
(删除的需求 — 必须说明原因和迁移方案)
|
|
363
|
+
|
|
364
|
+
## RENAMED Requirements
|
|
365
|
+
(重命名 — FROM: 旧名 / TO: 新名)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## 项目产生的目录结构
|
|
371
|
+
|
|
372
|
+
`specflow init` 后,你的项目会新增:
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
your-project/
|
|
376
|
+
├── specflow/ # 需求管理(应该跟踪到 git)
|
|
377
|
+
│ ├── config.yaml # 项目上下文配置
|
|
378
|
+
│ ├── specs/ # 主 specs(Source of Truth)
|
|
379
|
+
│ ├── changes/ # 活跃的变更
|
|
380
|
+
│ │ └── <name>/ # 每个变更的 artifact
|
|
381
|
+
│ │ ├── proposal.md
|
|
382
|
+
│ │ ├── specs/
|
|
383
|
+
│ │ ├── design.md
|
|
384
|
+
│ │ └── tasks.md
|
|
385
|
+
│ └── changes/archive/ # 归档的变更
|
|
386
|
+
│
|
|
387
|
+
└── .claude/
|
|
388
|
+
├── skills/specflow-*/ # 10 个技能(应该跟踪)
|
|
389
|
+
├── commands/specflow/ # 10 个命令别名(应该跟踪)
|
|
390
|
+
└── specflow/ # 资源文件(.gitignore 自动忽略)
|
|
391
|
+
├── prompts/
|
|
392
|
+
├── schemas/
|
|
393
|
+
└── templates/
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
建议的 git 策略:
|
|
397
|
+
- **跟踪**:`specflow/`、`.claude/skills/`、`.claude/commands/specflow/`(团队共享的规格和技能)
|
|
398
|
+
- **忽略**:`.claude/specflow/{prompts,schemas,templates}/`(`specflow init` 自动忽略,因为这些可由升级 specflow 重新生成)
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## 故障排查
|
|
403
|
+
|
|
404
|
+
### `specflow: command not found`
|
|
405
|
+
|
|
406
|
+
- 确认 `npm install -g` 成功
|
|
407
|
+
- 检查 `npm config get prefix` 下的 `bin` 目录是否在 PATH 里
|
|
408
|
+
|
|
409
|
+
### `No specflow project found at or above <dir>`
|
|
410
|
+
|
|
411
|
+
CLI 找不到项目根。确保:
|
|
412
|
+
- 你在一个跑过 `specflow init` 的项目目录里(或其子目录)
|
|
413
|
+
- `specflow/config.yaml` 存在
|
|
414
|
+
|
|
415
|
+
### `错误: Change "xxx" already exists`
|
|
416
|
+
|
|
417
|
+
变更名冲突。要么用不同名字,要么先归档已有的。
|
|
418
|
+
|
|
419
|
+
### Node 版本不兼容
|
|
420
|
+
|
|
421
|
+
SpecFlow 需要 Node ≥ 20.19.0。用 `nvm` 切版本:
|
|
422
|
+
```bash
|
|
423
|
+
nvm install 20
|
|
424
|
+
nvm use 20
|
|
425
|
+
npm install -g specflow
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### code-review-graph 安装失败
|
|
429
|
+
|
|
430
|
+
`/specflow:scan` 规划在 v0.3 实现时会用到 code-review-graph(当前在 optionalDependencies 里占位)。这个依赖是从 GitHub 安装的,如果网络问题导致失败,**不影响任何 v0.2.x 功能**——scan 本身在 v0.2.x 不可用,其余所有命令与此依赖无关。
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## 来源与许可
|
|
435
|
+
|
|
436
|
+
SpecFlow 基于两个开源项目构建(均为 MIT 许可):
|
|
437
|
+
- [OpenSpec](https://github.com/Fission-AI/OpenSpec) — artifact graph、delta merge、validation 等核心运行时
|
|
438
|
+
- [Superpowers](https://github.com/obra/superpowers) — brainstorming、TDD、debugging、code review 等 prompt
|
|
439
|
+
|
|
440
|
+
所有来源内容已按 SpecFlow 风格改写,通过 `<!-- SOURCE: ... -->` 注释标注出处。
|
|
441
|
+
|
|
442
|
+
**许可证:MIT**
|
package/bin/specflow.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command: specflow change archive <name>
|
|
3
|
+
*
|
|
4
|
+
* Archives a completed change by validating, applying deltas, and moving to archive.
|
|
5
|
+
*/
|
|
6
|
+
import type { Command } from 'commander';
|
|
7
|
+
import type { ArchiveOptions, ArchiveResult } from '../../core/archive.js';
|
|
8
|
+
/**
|
|
9
|
+
* Archives a change, throwing on failure.
|
|
10
|
+
*
|
|
11
|
+
* This is a thin wrapper around the core archiveChange function that:
|
|
12
|
+
* 1. Validates the change directory exists
|
|
13
|
+
* 2. Delegates to archiveChange (with optional --force)
|
|
14
|
+
* 3. Throws with error details if validation or archiving fails
|
|
15
|
+
*
|
|
16
|
+
* @param changeName - The name of the change to archive
|
|
17
|
+
* @param projectRoot - Absolute path to the project root
|
|
18
|
+
* @param options - Optional archive options (e.g. force to bypass phase gate)
|
|
19
|
+
* @returns The archive result on success
|
|
20
|
+
* @throws When the change does not exist, validation fails, or archiving fails
|
|
21
|
+
*/
|
|
22
|
+
export declare function archiveChangeCommand(changeName: string, projectRoot: string, options?: ArchiveOptions): Promise<ArchiveResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Registers the `change archive` subcommand with Commander.
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerChangeArchiveCommand(changeCmd: Command): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command: specflow change archive <name>
|
|
3
|
+
*
|
|
4
|
+
* Archives a completed change by validating, applying deltas, and moving to archive.
|
|
5
|
+
*/
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import { archiveChange } from '../../core/archive.js';
|
|
9
|
+
import { requireProjectRoot } from '../../utils/project-root.js';
|
|
10
|
+
/**
|
|
11
|
+
* Archives a change, throwing on failure.
|
|
12
|
+
*
|
|
13
|
+
* This is a thin wrapper around the core archiveChange function that:
|
|
14
|
+
* 1. Validates the change directory exists
|
|
15
|
+
* 2. Delegates to archiveChange (with optional --force)
|
|
16
|
+
* 3. Throws with error details if validation or archiving fails
|
|
17
|
+
*
|
|
18
|
+
* @param changeName - The name of the change to archive
|
|
19
|
+
* @param projectRoot - Absolute path to the project root
|
|
20
|
+
* @param options - Optional archive options (e.g. force to bypass phase gate)
|
|
21
|
+
* @returns The archive result on success
|
|
22
|
+
* @throws When the change does not exist, validation fails, or archiving fails
|
|
23
|
+
*/
|
|
24
|
+
export async function archiveChangeCommand(changeName, projectRoot, options = {}) {
|
|
25
|
+
const changeDir = join(projectRoot, 'specflow', 'changes', changeName);
|
|
26
|
+
if (!fs.existsSync(changeDir)) {
|
|
27
|
+
throw new Error(`Change "${changeName}" not found at ${changeDir}`);
|
|
28
|
+
}
|
|
29
|
+
const result = await archiveChange(changeName, projectRoot, options);
|
|
30
|
+
if (!result.success) {
|
|
31
|
+
throw new Error(`Archive failed for "${changeName}":\n${result.errors.join('\n')}`);
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Registers the `change archive` subcommand with Commander.
|
|
37
|
+
*/
|
|
38
|
+
export function registerChangeArchiveCommand(changeCmd) {
|
|
39
|
+
changeCmd
|
|
40
|
+
.command('archive <name>')
|
|
41
|
+
.description('Archive a completed change')
|
|
42
|
+
.option('--force', 'Archive even if the change is not in phase=built')
|
|
43
|
+
.action(async (name, opts) => {
|
|
44
|
+
const projectRoot = requireProjectRoot();
|
|
45
|
+
const result = await archiveChangeCommand(name, projectRoot, {
|
|
46
|
+
force: opts.force ?? false,
|
|
47
|
+
});
|
|
48
|
+
console.info(`Archived change "${name}" to ${result.archivePath}`);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command: specflow change new <name>
|
|
3
|
+
*
|
|
4
|
+
* Creates a new change directory with .specflow.yaml metadata.
|
|
5
|
+
*/
|
|
6
|
+
import type { Command } from 'commander';
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new change directory with initial metadata.
|
|
9
|
+
*
|
|
10
|
+
* @param name - The change name (kebab-case)
|
|
11
|
+
* @param projectRoot - Absolute path to the project root
|
|
12
|
+
* @throws When the name is invalid or the change already exists
|
|
13
|
+
*/
|
|
14
|
+
export declare function createChange(name: string, projectRoot: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Registers the `change new` subcommand with Commander.
|
|
17
|
+
*/
|
|
18
|
+
export declare function registerChangeNewCommand(changeCmd: Command): void;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command: specflow change new <name>
|
|
3
|
+
*
|
|
4
|
+
* Creates a new change directory with .specflow.yaml metadata.
|
|
5
|
+
*/
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { validateChangeName, writeChangeMetadata } from '../../utils/change-utils.js';
|
|
8
|
+
import { directoryExists } from '../../utils/file-system.js';
|
|
9
|
+
import { requireProjectRoot } from '../../utils/project-root.js';
|
|
10
|
+
const CHANGES_REL_PATH = 'specflow/changes';
|
|
11
|
+
/**
|
|
12
|
+
* Returns today's date as YYYY-MM-DD string.
|
|
13
|
+
*/
|
|
14
|
+
function todayDate() {
|
|
15
|
+
const now = new Date();
|
|
16
|
+
const year = now.getFullYear();
|
|
17
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
18
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
19
|
+
return `${year}-${month}-${day}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new change directory with initial metadata.
|
|
23
|
+
*
|
|
24
|
+
* @param name - The change name (kebab-case)
|
|
25
|
+
* @param projectRoot - Absolute path to the project root
|
|
26
|
+
* @throws When the name is invalid or the change already exists
|
|
27
|
+
*/
|
|
28
|
+
export async function createChange(name, projectRoot) {
|
|
29
|
+
validateChangeName(name);
|
|
30
|
+
const changeDir = join(projectRoot, CHANGES_REL_PATH, name);
|
|
31
|
+
if (await directoryExists(changeDir)) {
|
|
32
|
+
throw new Error(`Change "${name}" already exists at ${changeDir}`);
|
|
33
|
+
}
|
|
34
|
+
const metadata = {
|
|
35
|
+
schema: 'specflow',
|
|
36
|
+
created: todayDate(),
|
|
37
|
+
phase: 'plan',
|
|
38
|
+
};
|
|
39
|
+
await writeChangeMetadata(name, metadata, projectRoot);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Registers the `change new` subcommand with Commander.
|
|
43
|
+
*/
|
|
44
|
+
export function registerChangeNewCommand(changeCmd) {
|
|
45
|
+
changeCmd
|
|
46
|
+
.command('new <name>')
|
|
47
|
+
.description('Create a new change directory')
|
|
48
|
+
.action(async (name) => {
|
|
49
|
+
const projectRoot = requireProjectRoot();
|
|
50
|
+
await createChange(name, projectRoot);
|
|
51
|
+
console.info(`Created change: ${name}`);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI command: specflow change phase <name> [--set <value>]
|
|
3
|
+
*
|
|
4
|
+
* Read or update the lifecycle phase of a change.
|
|
5
|
+
*/
|
|
6
|
+
import type { Command } from 'commander';
|
|
7
|
+
import type { ChangePhase } from '../../utils/change-utils.js';
|
|
8
|
+
/**
|
|
9
|
+
* Reads the current phase of a change.
|
|
10
|
+
*
|
|
11
|
+
* @param name - Name of the change
|
|
12
|
+
* @param projectRoot - Absolute path to the project root
|
|
13
|
+
* @returns The current phase, or undefined for legacy files without a phase field
|
|
14
|
+
* @throws When the change does not exist
|
|
15
|
+
*/
|
|
16
|
+
export declare function getPhase(name: string, projectRoot: string): Promise<ChangePhase | undefined>;
|
|
17
|
+
/**
|
|
18
|
+
* Sets the phase of a change, validating the phase value first.
|
|
19
|
+
*
|
|
20
|
+
* @param name - Name of the change
|
|
21
|
+
* @param phase - The new phase value (validated against CHANGE_PHASES)
|
|
22
|
+
* @param projectRoot - Absolute path to the project root
|
|
23
|
+
* @throws When the phase is invalid or the change does not exist
|
|
24
|
+
*/
|
|
25
|
+
export declare function setPhase(name: string, phase: string, projectRoot: string): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Registers the `change phase` subcommand with Commander.
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
* specflow change phase <name> # print current phase
|
|
31
|
+
* specflow change phase <name> --set plan # update phase
|
|
32
|
+
*/
|
|
33
|
+
export declare function registerChangePhaseCommand(changeCmd: Command): void;
|