@gavin-hjw/sddflow 0.3.2
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 +21 -0
- package/README.md +152 -0
- package/README.zh-CN.md +151 -0
- package/bin/sddflow.js +5 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.js +115 -0
- package/dist/cli/status.d.ts +2 -0
- package/dist/cli/status.js +78 -0
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.js +32 -0
- package/dist/core/constants.d.ts +23 -0
- package/dist/core/constants.js +34 -0
- package/dist/core/dependency-check.d.ts +29 -0
- package/dist/core/dependency-check.js +87 -0
- package/dist/core/skill-generator.d.ts +8 -0
- package/dist/core/skill-generator.js +242 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.js +9 -0
- package/dist/utils/shell.d.ts +6 -0
- package/dist/utils/shell.js +39 -0
- package/package.json +49 -0
- package/scripts/postinstall.js +12 -0
- package/templates/SKILL.md +87 -0
- package/templates/amend.md +136 -0
- package/templates/brainstorming.md +72 -0
- package/templates/build.md +81 -0
- package/templates/close.md +91 -0
- package/templates/proposal.md +62 -0
- package/templates/spec.md +111 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Emerson Towne
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# @gavin-hjw/sddflow
|
|
2
|
+
|
|
3
|
+
[中文文档](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
OpenSpec + Superpowers workflow orchestrator — bridging requirements specs and engineering execution, eliminating the format gap.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @gavin-hjw/sddflow
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Initialize a project
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cd your-project
|
|
19
|
+
sddflow init --tools claude
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`init` will automatically:
|
|
23
|
+
1. Detect and guide OpenSpec CLI installation
|
|
24
|
+
2. Detect Superpowers and show install instructions
|
|
25
|
+
3. Check if OpenSpec is initialized in the project
|
|
26
|
+
4. Generate sddflow skills to the selected tools' local skill directories, such as `.claude/skills/sddflow/`, `.codex/skills/sddflow/`, `.cursor/skills/sddflow/`, or `.opencode/commands/sddflow/`
|
|
27
|
+
|
|
28
|
+
Supported tools: `claude`, `codex`, `cursor`, `opencode` (comma-separated, e.g. `--tools claude,codex`)
|
|
29
|
+
|
|
30
|
+
### Install skills globally
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
sddflow init --tools claude -g
|
|
34
|
+
sddflow init --tools claude,codex,cursor,opencode --global
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
With `-g` / `--global`, `sddflow` installs skills under the selected tools' home directories:
|
|
38
|
+
|
|
39
|
+
| Tool | Global skill path |
|
|
40
|
+
|------|-------------------|
|
|
41
|
+
| `claude` | `~/.claude/skills/sddflow/` |
|
|
42
|
+
| `codex` | `~/.codex/skills/sddflow/` |
|
|
43
|
+
| `cursor` | `~/.cursor/skills/sddflow/` |
|
|
44
|
+
| `opencode` | `~/.opencode/commands/sddflow/` |
|
|
45
|
+
|
|
46
|
+
### Check status
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
sddflow status
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Shows dependency installation status and active changes in the project.
|
|
53
|
+
|
|
54
|
+
### Update skills
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
sddflow update
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Re-generates project skills after upgrading the npm package.
|
|
61
|
+
|
|
62
|
+
## Workflow Commands
|
|
63
|
+
|
|
64
|
+
Canonical usage is `/sddflow <phase>`. For Claude Code, Codex, and Cursor,
|
|
65
|
+
`sddflow` also generates visible phase aliases such as `/sddflow-spec` or
|
|
66
|
+
`$sddflow-spec` so typing `sddflow` in the command/skill picker surfaces the
|
|
67
|
+
available phases. OpenCode keeps its native command-tree form under
|
|
68
|
+
`/sddflow/spec`, `/sddflow/build`, and so on.
|
|
69
|
+
|
|
70
|
+
| Command | Phase | Description |
|
|
71
|
+
|---------|-------|-------------|
|
|
72
|
+
| `/sddflow proposal` | proposal | Lightweight capture — 3-5 questions to converge on requirements |
|
|
73
|
+
| `/sddflow brainstorming` | brainstorming | Deep design — multi-round tradeoff exploration |
|
|
74
|
+
| `/sddflow spec` | spec | Call OpenSpec to generate specs + auto-translate to plan-ready.md |
|
|
75
|
+
| `/sddflow amend` | amend | Revise requirements/specs before close and update plan-ready.md |
|
|
76
|
+
| `/sddflow build` | build | Call Superpowers to execute implementation |
|
|
77
|
+
| `/sddflow close` | close | Verify consistency + archive |
|
|
78
|
+
|
|
79
|
+
## Dependency Strategy
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Best with: OpenSpec + Superpowers
|
|
83
|
+
Works without them: yes, with manual-file fallback
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Dependency | Install | Fallback when missing |
|
|
87
|
+
|------------|---------|----------------------|
|
|
88
|
+
| OpenSpec | `npm install -g @fission-ai/openspec@latest` | Manually create `openspec/changes/` directories and files |
|
|
89
|
+
| Superpowers | `/plugin install superpowers@claude-plugins-official` | Manually break down plan-ready.md steps in build phase |
|
|
90
|
+
|
|
91
|
+
### Dual-layer dependency check
|
|
92
|
+
|
|
93
|
+
| Layer | Mechanism | When missing |
|
|
94
|
+
|-------|-----------|-------------|
|
|
95
|
+
| **Init time** | Detect OpenSpec CLI from `PATH`; detect project OpenSpec in `./openspec/`; detect Superpowers in the selected tools' local/global skill dirs | Non-blocking, skills still generated |
|
|
96
|
+
| **Runtime** | Dependency check injected into SKILL.md | Build phase falls back to manual step-by-step execution |
|
|
97
|
+
|
|
98
|
+
## Architecture
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
User Requirements
|
|
102
|
+
│
|
|
103
|
+
├── Quick ──→ /sddflow proposal ──┐
|
|
104
|
+
│ 3-5 questions │
|
|
105
|
+
│ ├─→ proposal.md
|
|
106
|
+
└── Deep ───→ /sddflow brainstorming ─┘ (openspec/changes/<name>/)
|
|
107
|
+
Multi-round exploration
|
|
108
|
+
│
|
|
109
|
+
┌──────────▼───────────┐
|
|
110
|
+
│ /sddflow spec │
|
|
111
|
+
│ OpenSpec generates │
|
|
112
|
+
└──────────┬───────────┘
|
|
113
|
+
│
|
|
114
|
+
┌──────────▼───────────┐
|
|
115
|
+
│ Translation Layer │
|
|
116
|
+
│ Requirements → Eng │
|
|
117
|
+
└──────────┬───────────┘
|
|
118
|
+
│
|
|
119
|
+
plan-ready.md
|
|
120
|
+
│
|
|
121
|
+
┌──────────▼───────────┐
|
|
122
|
+
│ /sddflow build │
|
|
123
|
+
│ Superpowers execution │
|
|
124
|
+
│ TDD + checkpoint │
|
|
125
|
+
└──────────┬───────────┘
|
|
126
|
+
│
|
|
127
|
+
┌──────────▼───────────┐
|
|
128
|
+
│ /sddflow amend │
|
|
129
|
+
│ Requirement revision │
|
|
130
|
+
│ (only when needed) │
|
|
131
|
+
└──────────┬───────────┘
|
|
132
|
+
│
|
|
133
|
+
┌──────────▼───────────┐
|
|
134
|
+
│ /sddflow close │
|
|
135
|
+
│ Verify + archive │
|
|
136
|
+
└──────────────────────┘
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Acknowledgments
|
|
140
|
+
|
|
141
|
+
sddflow orchestrates two open-source projects:
|
|
142
|
+
|
|
143
|
+
| Project | Repository | License | Usage |
|
|
144
|
+
|---------|-----------|---------|-------|
|
|
145
|
+
| [OpenSpec](https://github.com/Fission-AI/OpenSpec) | `@fission-ai/openspec` | MIT | Generates structured spec files (proposal.md, design.md, specs/, tasks.md). sddflow calls its CLI and reads its output format. |
|
|
146
|
+
| [Superpowers](https://github.com/obra/superpowers) | `superpowers` plugin | MIT | Provides `writing-plans` skill for detailed implementation planning. sddflow delegates build-phase execution to its workflow. |
|
|
147
|
+
|
|
148
|
+
sddflow is a **standalone orchestrator** — it does not bundle, fork, or embed code from either project. Dependencies are detected at init/runtime, with manual fallback when either is not installed.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# @gavin-hjw/sddflow
|
|
2
|
+
|
|
3
|
+
[English](./README.md)
|
|
4
|
+
|
|
5
|
+
OpenSpec + Superpowers 工作流协调器,串联需求规格与工程执行,消除格式鸿沟。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @gavin-hjw/sddflow
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 使用
|
|
14
|
+
|
|
15
|
+
### 初始化项目
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cd your-project
|
|
19
|
+
sddflow init --tools claude
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`init` 会自动:
|
|
23
|
+
1. 检测并引导安装 OpenSpec CLI
|
|
24
|
+
2. 检测 Superpowers 并提示安装方式
|
|
25
|
+
3. 检测项目 OpenSpec 初始化状态
|
|
26
|
+
4. 生成 sddflow skills 到所选工具的项目级 skill 目录,如 `.claude/skills/sddflow/`、`.codex/skills/sddflow/`、`.cursor/skills/sddflow/` 或 `.opencode/commands/sddflow/`
|
|
27
|
+
|
|
28
|
+
支持的工具:`claude`、`codex`、`cursor`、`opencode`(逗号分隔,如 `--tools claude,codex`)
|
|
29
|
+
|
|
30
|
+
### 安装到全局 skills
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
sddflow init --tools claude -g
|
|
34
|
+
sddflow init --tools claude,codex,cursor,opencode --global
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
加 `-g` / `--global` 后,`sddflow` 会把 skills 安装到所选工具的全局目录:
|
|
38
|
+
|
|
39
|
+
| 工具 | 全局 skill 路径 |
|
|
40
|
+
|------|-----------------|
|
|
41
|
+
| `claude` | `~/.claude/skills/sddflow/` |
|
|
42
|
+
| `codex` | `~/.codex/skills/sddflow/` |
|
|
43
|
+
| `cursor` | `~/.cursor/skills/sddflow/` |
|
|
44
|
+
| `opencode` | `~/.opencode/commands/sddflow/` |
|
|
45
|
+
|
|
46
|
+
### 查看状态
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
sddflow status
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
显示依赖安装状态和项目中的活跃变更。
|
|
53
|
+
|
|
54
|
+
### 更新 skills
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
sddflow update
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
升级 npm 包后运行,重新生成项目内的 skills 文件。
|
|
61
|
+
|
|
62
|
+
## 工作流命令
|
|
63
|
+
|
|
64
|
+
规范调用方式是 `/sddflow <阶段>`。为了改善补全体验,Claude Code、
|
|
65
|
+
Codex 和 Cursor 会额外生成可见的阶段别名,例如 `/sddflow-spec` 或
|
|
66
|
+
`$sddflow-spec`,这样在命令/skill 选择器里输入 `sddflow` 时能看到可用阶段。
|
|
67
|
+
OpenCode 保持原生命令树形式,例如 `/sddflow/spec`、`/sddflow/build`。
|
|
68
|
+
|
|
69
|
+
| 命令 | 阶段 | 说明 |
|
|
70
|
+
|------|------|------|
|
|
71
|
+
| `/sddflow proposal` | proposal | 轻量提问,3-5 问快速收敛需求 |
|
|
72
|
+
| `/sddflow brainstorming` | brainstorming | 深度设计,多轮方案探索 |
|
|
73
|
+
| `/sddflow spec` | spec | 调用 OpenSpec 生成规格 + 自动翻译 |
|
|
74
|
+
| `/sddflow amend` | amend | close 前修订需求/规格并更新 plan-ready.md |
|
|
75
|
+
| `/sddflow build` | build | 调用 Superpowers 执行实现 |
|
|
76
|
+
| `/sddflow close` | close | 验证一致性 + 归档 |
|
|
77
|
+
|
|
78
|
+
## 依赖策略
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Best with: OpenSpec + Superpowers
|
|
82
|
+
Works without them: yes, with manual-file fallback
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
| 依赖 | 安装方式 | 缺失时降级 |
|
|
86
|
+
|------|----------|-----------|
|
|
87
|
+
| OpenSpec | `npm install -g @fission-ai/openspec@latest` | 手动创建 `openspec/changes/` 目录和文件 |
|
|
88
|
+
| Superpowers | `/plugin install superpowers@claude-plugins-official` | build 阶段手动拆解 plan-ready.md 步骤执行 |
|
|
89
|
+
|
|
90
|
+
### 双层依赖保障
|
|
91
|
+
|
|
92
|
+
| 层 | 机制 | 缺失时 |
|
|
93
|
+
|----|------|--------|
|
|
94
|
+
| **init 时** | 从 `PATH` 检测 OpenSpec CLI;从 `./openspec/` 检测当前项目 OpenSpec;从所选工具的本地/全局 skill 目录检测 Superpowers | 不阻断,继续生成 skills |
|
|
95
|
+
| **运行时** | SKILL.md 注入依赖检测段 | build 阶段降级为手动拆解步骤执行 |
|
|
96
|
+
|
|
97
|
+
## 架构
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
用户需求
|
|
101
|
+
│
|
|
102
|
+
├── 轻量 ──→ /sddflow proposal ──┐
|
|
103
|
+
│ 3-5问快速收敛 │
|
|
104
|
+
│ ├─→ proposal.md
|
|
105
|
+
└── 深度 ──→ /sddflow brainstorming ─┘ (openspec/changes/<name>/)
|
|
106
|
+
多轮方案探索
|
|
107
|
+
│
|
|
108
|
+
┌──────────▼───────────┐
|
|
109
|
+
│ /sddflow spec │
|
|
110
|
+
│ OpenSpec 生成规格 │
|
|
111
|
+
└──────────┬───────────┘
|
|
112
|
+
│
|
|
113
|
+
┌──────────▼───────────┐
|
|
114
|
+
│ 翻译层 (核心) │
|
|
115
|
+
│ 需求视角 → 工程视角 │
|
|
116
|
+
└──────────┬───────────┘
|
|
117
|
+
│
|
|
118
|
+
plan-ready.md
|
|
119
|
+
│
|
|
120
|
+
┌──────────▼───────────┐
|
|
121
|
+
│ /sddflow build │
|
|
122
|
+
│ Superpowers 执行 │
|
|
123
|
+
│ TDD 铁律 + 断点恢复 │
|
|
124
|
+
└──────────┬───────────┘
|
|
125
|
+
│
|
|
126
|
+
┌──────────▼───────────┐
|
|
127
|
+
│ /sddflow amend │
|
|
128
|
+
│ 需求变更修订 │
|
|
129
|
+
│ (仅需要时) │
|
|
130
|
+
└──────────┬───────────┘
|
|
131
|
+
│
|
|
132
|
+
┌──────────▼───────────┐
|
|
133
|
+
│ /sddflow close │
|
|
134
|
+
│ 验证一致性 + 归档 │
|
|
135
|
+
└──────────────────────┘
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 致谢
|
|
139
|
+
|
|
140
|
+
sddflow 编排了以下两个开源项目:
|
|
141
|
+
|
|
142
|
+
| 项目 | 仓库 | 许可证 | 使用方式 |
|
|
143
|
+
|------|------|--------|----------|
|
|
144
|
+
| [OpenSpec](https://github.com/Fission-AI/OpenSpec) | `@fission-ai/openspec` | MIT | 生成结构化规格文件(proposal.md、design.md、specs/、tasks.md)。sddflow 调用其 CLI 并读取其输出格式。 |
|
|
145
|
+
| [Superpowers](https://github.com/obra/superpowers) | `superpowers` 插件 | MIT | 提供 `writing-plans` skill 用于生成详细实现计划。sddflow 在 build 阶段委托其工作流执行。 |
|
|
146
|
+
|
|
147
|
+
sddflow 是**独立编排器** — 不捆绑、不分叉、不嵌入任何项目的代码。依赖在 init/运行时检测,任一缺失时降级为手动模式。
|
|
148
|
+
|
|
149
|
+
## License
|
|
150
|
+
|
|
151
|
+
MIT
|
package/bin/sddflow.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function run(): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import { initCommand } from './init.js';
|
|
4
|
+
import { statusCommand } from './status.js';
|
|
5
|
+
import { updateCommand } from './update.js';
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const pkg = require('../../package.json');
|
|
8
|
+
export function run() {
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name('sddflow')
|
|
12
|
+
.description('OpenSpec + Superpowers workflow orchestrator (SDDFlow)')
|
|
13
|
+
.version(pkg.version);
|
|
14
|
+
program.addCommand(initCommand);
|
|
15
|
+
program.addCommand(statusCommand);
|
|
16
|
+
program.addCommand(updateCommand);
|
|
17
|
+
program.parse();
|
|
18
|
+
}
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { checkDependencies, tryAutoInstall, checkOpenSpecInitialized, writeState } from '../core/dependency-check.js';
|
|
4
|
+
import { generateSkills } from '../core/skill-generator.js';
|
|
5
|
+
import { TOOL_PATHS, DEPS } from '../core/constants.js';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
import { exec } from '../utils/shell.js';
|
|
8
|
+
const SUPPORTED_TOOLS = Object.keys(TOOL_PATHS);
|
|
9
|
+
export const initCommand = new Command('init')
|
|
10
|
+
.description('Initialize sddflow skills in the current project')
|
|
11
|
+
.option('-t, --tools <tools>', 'Target tools, comma-separated', 'claude')
|
|
12
|
+
.option('-g, --global', 'Install skills globally under home tool directories')
|
|
13
|
+
.action(async (options) => {
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
const tools = options.tools.split(',').map((t) => t.trim());
|
|
16
|
+
const installGlobally = Boolean(options.global);
|
|
17
|
+
logger.blank();
|
|
18
|
+
logger.info(`sddflow init — ${installGlobally ? 'global skill setup' : 'workflow orchestrator setup'}`);
|
|
19
|
+
logger.blank();
|
|
20
|
+
// Step 1: Check OpenSpec
|
|
21
|
+
logger.step('Checking OpenSpec ...');
|
|
22
|
+
let depStatus = checkDependencies({ cwd, tools });
|
|
23
|
+
if (!depStatus.openspec.installed) {
|
|
24
|
+
logger.warn('OpenSpec CLI not installed');
|
|
25
|
+
const { installOpenSpec } = await inquirer.prompt([
|
|
26
|
+
{
|
|
27
|
+
type: 'confirm',
|
|
28
|
+
name: 'installOpenSpec',
|
|
29
|
+
message: `Auto-install? (npm install -g ${DEPS.openspec.npmPkg}@latest)`,
|
|
30
|
+
default: true,
|
|
31
|
+
},
|
|
32
|
+
]);
|
|
33
|
+
if (installOpenSpec) {
|
|
34
|
+
const ok = tryAutoInstall(DEPS.openspec.npmPkg);
|
|
35
|
+
depStatus = checkDependencies({ cwd, tools }); // recheck
|
|
36
|
+
if (ok)
|
|
37
|
+
depStatus.openspec.autoInstalled = true;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
logger.warn('Skipped OpenSpec install — spec phase will use manual fallback');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
logger.success(`OpenSpec CLI installed${depStatus.openspec.version ? ` (v${depStatus.openspec.version})` : ''}`);
|
|
45
|
+
}
|
|
46
|
+
// Step 2: Check Superpowers
|
|
47
|
+
logger.step('Checking Superpowers ...');
|
|
48
|
+
if (!depStatus.superpowers.installed) {
|
|
49
|
+
logger.warn('Superpowers not installed');
|
|
50
|
+
logger.info(DEPS.superpowers.installHint);
|
|
51
|
+
logger.info('Re-run sddflow init after installing, or build phase will use manual fallback');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
logger.success(`Superpowers installed${depStatus.superpowers.path ? ` (${depStatus.superpowers.path})` : ''}`);
|
|
55
|
+
}
|
|
56
|
+
if (installGlobally) {
|
|
57
|
+
logger.step('Skipping project OpenSpec initialization for global install');
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Step 3: Check if OpenSpec is initialized in project
|
|
61
|
+
logger.step('Checking project OpenSpec initialization ...');
|
|
62
|
+
if (!checkOpenSpecInitialized(cwd)) {
|
|
63
|
+
if (depStatus.openspec.installed) {
|
|
64
|
+
const { initOpenSpec } = await inquirer.prompt([
|
|
65
|
+
{
|
|
66
|
+
type: 'confirm',
|
|
67
|
+
name: 'initOpenSpec',
|
|
68
|
+
message: 'OpenSpec not initialized in this project. Run openspec init?',
|
|
69
|
+
default: true,
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
if (initOpenSpec) {
|
|
73
|
+
const toolsFlag = tools.map((t) => t).join(',');
|
|
74
|
+
exec(`openspec init --tools ${toolsFlag}`, { stdio: 'inherit' });
|
|
75
|
+
logger.success('OpenSpec project initialized');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
logger.info('OpenSpec not initialized — directories will be auto-created on first /sddflow proposal');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
logger.success('OpenSpec project initialized');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Step 4: Generate skills
|
|
87
|
+
logger.step('Generating sddflow skills ...');
|
|
88
|
+
generateSkills({ cwd, tools, depStatus, global: installGlobally });
|
|
89
|
+
if (!installGlobally) {
|
|
90
|
+
// Step 5: Write state
|
|
91
|
+
writeState(cwd, {
|
|
92
|
+
openspec: depStatus.openspec.installed,
|
|
93
|
+
superpowers: depStatus.superpowers.installed,
|
|
94
|
+
openspecProjectInitialized: checkOpenSpecInitialized(cwd),
|
|
95
|
+
createdAt: new Date().toISOString(),
|
|
96
|
+
tools,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
logger.blank();
|
|
100
|
+
logger.success('sddflow initialized!');
|
|
101
|
+
logger.blank();
|
|
102
|
+
if (!depStatus.superpowers.installed) {
|
|
103
|
+
logger.warn('Note: Superpowers not installed — /sddflow build will use manual execution mode');
|
|
104
|
+
logger.info(` Install with: ${DEPS.superpowers.installHint}`);
|
|
105
|
+
logger.blank();
|
|
106
|
+
}
|
|
107
|
+
logger.info('Available commands:');
|
|
108
|
+
logger.info(' /sddflow proposal Quick requirement capture');
|
|
109
|
+
logger.info(' /sddflow brainstorming Deep design exploration');
|
|
110
|
+
logger.info(' /sddflow spec Generate specs + translate');
|
|
111
|
+
logger.info(' /sddflow amend Revise requirements before close');
|
|
112
|
+
logger.info(' /sddflow build Execute implementation');
|
|
113
|
+
logger.info(' /sddflow close Verify + archive');
|
|
114
|
+
logger.blank();
|
|
115
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { checkDependencies, readState, checkOpenSpecInitialized } from '../core/dependency-check.js';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
import { dirExists } from '../utils/shell.js';
|
|
7
|
+
export const statusCommand = new Command('status')
|
|
8
|
+
.description('Show dependency status and active changes')
|
|
9
|
+
.action(() => {
|
|
10
|
+
const cwd = process.cwd();
|
|
11
|
+
logger.blank();
|
|
12
|
+
logger.info('sddflow status');
|
|
13
|
+
logger.blank();
|
|
14
|
+
const state = readState(cwd);
|
|
15
|
+
// Dependencies
|
|
16
|
+
logger.step('Dependencies:');
|
|
17
|
+
const depStatus = checkDependencies({ cwd, tools: state?.tools });
|
|
18
|
+
if (depStatus.openspec.installed) {
|
|
19
|
+
logger.success(`OpenSpec CLI${depStatus.openspec.version ? ` v${depStatus.openspec.version}` : ''}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
logger.warn('OpenSpec CLI — not installed');
|
|
23
|
+
}
|
|
24
|
+
if (depStatus.superpowers.installed) {
|
|
25
|
+
logger.success(`Superpowers${depStatus.superpowers.path ? ` (${depStatus.superpowers.path})` : ''}`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
logger.warn('Superpowers — not installed (build phase will use manual mode)');
|
|
29
|
+
}
|
|
30
|
+
logger.blank();
|
|
31
|
+
// Project state
|
|
32
|
+
logger.step('Project:');
|
|
33
|
+
if (state) {
|
|
34
|
+
logger.success(`Initialized (${state.tools.join(', ')})`);
|
|
35
|
+
logger.info(` Created at: ${state.createdAt}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
logger.warn('Not initialized — run sddflow init');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (checkOpenSpecInitialized(cwd)) {
|
|
42
|
+
logger.success('OpenSpec project initialized');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
logger.warn('OpenSpec project not initialized');
|
|
46
|
+
}
|
|
47
|
+
logger.blank();
|
|
48
|
+
// Active changes
|
|
49
|
+
logger.step('Active changes:');
|
|
50
|
+
const changesDir = path.join(cwd, 'openspec', 'changes');
|
|
51
|
+
if (!dirExists(changesDir)) {
|
|
52
|
+
logger.info(' None');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const entries = fs.readdirSync(changesDir, { withFileTypes: true })
|
|
56
|
+
.filter((d) => d.isDirectory() && d.name !== 'archive');
|
|
57
|
+
if (entries.length === 0) {
|
|
58
|
+
logger.info(' None');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
const changeDir = path.join(changesDir, entry.name);
|
|
63
|
+
const hasPlanReady = fs.existsSync(path.join(changeDir, 'plan-ready.md'));
|
|
64
|
+
const hasProposal = fs.existsSync(path.join(changeDir, 'proposal.md'));
|
|
65
|
+
let status = '';
|
|
66
|
+
if (hasPlanReady) {
|
|
67
|
+
status = '→ ready for /sddflow build or /sddflow amend';
|
|
68
|
+
}
|
|
69
|
+
else if (hasProposal) {
|
|
70
|
+
status = '→ needs /sddflow spec';
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
status = '→ needs /sddflow proposal';
|
|
74
|
+
}
|
|
75
|
+
logger.info(` ${entry.name} ${status}`);
|
|
76
|
+
}
|
|
77
|
+
logger.blank();
|
|
78
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { checkDependencies, readState, writeState, checkOpenSpecInitialized } from '../core/dependency-check.js';
|
|
3
|
+
import { generateSkills } from '../core/skill-generator.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
export const updateCommand = new Command('update')
|
|
6
|
+
.description('Regenerate sddflow skills in the current project')
|
|
7
|
+
.action(() => {
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
const state = readState(cwd);
|
|
10
|
+
if (!state) {
|
|
11
|
+
logger.error('Project not initialized — run sddflow init first');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
logger.blank();
|
|
15
|
+
logger.info('sddflow update — regenerating skills');
|
|
16
|
+
logger.blank();
|
|
17
|
+
const depStatus = checkDependencies({ cwd, tools: state.tools });
|
|
18
|
+
generateSkills({
|
|
19
|
+
cwd,
|
|
20
|
+
tools: state.tools,
|
|
21
|
+
depStatus,
|
|
22
|
+
});
|
|
23
|
+
writeState(cwd, {
|
|
24
|
+
...state,
|
|
25
|
+
openspec: depStatus.openspec.installed,
|
|
26
|
+
superpowers: depStatus.superpowers.installed,
|
|
27
|
+
openspecProjectInitialized: checkOpenSpecInitialized(cwd),
|
|
28
|
+
});
|
|
29
|
+
logger.blank();
|
|
30
|
+
logger.success('Skills updated');
|
|
31
|
+
logger.blank();
|
|
32
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const PKG_NAME = "@gavin-hjw/sddflow";
|
|
2
|
+
export declare const PKG_BIN = "sddflow";
|
|
3
|
+
export declare const SKILL_NAME = "sddflow";
|
|
4
|
+
export declare const COMMAND_PREFIX = "/sddflow";
|
|
5
|
+
export declare const DEPS: {
|
|
6
|
+
readonly openspec: {
|
|
7
|
+
readonly name: "OpenSpec";
|
|
8
|
+
readonly cliCmd: "openspec";
|
|
9
|
+
readonly npmPkg: "@fission-ai/openspec";
|
|
10
|
+
readonly installHint: "npm install -g @fission-ai/openspec@latest";
|
|
11
|
+
readonly autoInstallable: true;
|
|
12
|
+
};
|
|
13
|
+
readonly superpowers: {
|
|
14
|
+
readonly name: "Superpowers";
|
|
15
|
+
readonly checkPath: "writing-plans/SKILL.md";
|
|
16
|
+
readonly installHint: "请在当前工具中安装 Superpowers writing-plans skill(Claude Code: /plugin install superpowers@claude-plugins-official)";
|
|
17
|
+
readonly autoInstallable: false;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare const TOOL_PATHS: Record<string, {
|
|
21
|
+
skillsDir: string;
|
|
22
|
+
commandsDir?: string;
|
|
23
|
+
}>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const PKG_NAME = '@gavin-hjw/sddflow';
|
|
2
|
+
export const PKG_BIN = 'sddflow';
|
|
3
|
+
export const SKILL_NAME = 'sddflow';
|
|
4
|
+
export const COMMAND_PREFIX = '/sddflow';
|
|
5
|
+
export const DEPS = {
|
|
6
|
+
openspec: {
|
|
7
|
+
name: 'OpenSpec',
|
|
8
|
+
cliCmd: 'openspec',
|
|
9
|
+
npmPkg: '@fission-ai/openspec',
|
|
10
|
+
installHint: 'npm install -g @fission-ai/openspec@latest',
|
|
11
|
+
autoInstallable: true,
|
|
12
|
+
},
|
|
13
|
+
superpowers: {
|
|
14
|
+
name: 'Superpowers',
|
|
15
|
+
checkPath: 'writing-plans/SKILL.md',
|
|
16
|
+
installHint: '请在当前工具中安装 Superpowers writing-plans skill(Claude Code: /plugin install superpowers@claude-plugins-official)',
|
|
17
|
+
autoInstallable: false,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
export const TOOL_PATHS = {
|
|
21
|
+
claude: {
|
|
22
|
+
skillsDir: '.claude/skills',
|
|
23
|
+
commandsDir: '.claude/commands',
|
|
24
|
+
},
|
|
25
|
+
codex: {
|
|
26
|
+
skillsDir: '.codex/skills',
|
|
27
|
+
},
|
|
28
|
+
cursor: {
|
|
29
|
+
skillsDir: '.cursor/skills',
|
|
30
|
+
},
|
|
31
|
+
opencode: {
|
|
32
|
+
skillsDir: '.opencode/commands',
|
|
33
|
+
},
|
|
34
|
+
};
|