@lininn/openflow 0.1.0 → 0.1.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/README.md +60 -40
- package/README.zh-CN.md +123 -0
- package/dist/cli/index.js +1 -1
- package/dist/cli/init.js +27 -27
- package/dist/cli/status.js +13 -14
- package/dist/cli/update.js +4 -4
- package/dist/core/dependency-check.js +3 -3
- package/dist/core/skill-generator.js +19 -19
- package/package.json +1 -1
- package/scripts/postinstall.js +4 -4
- package/templates/SKILL.md +1 -1
- package/templates/brainstorming.md +1 -1
- package/templates/build.md +1 -1
- package/templates/close.md +1 -1
- package/templates/proposal.md +1 -1
- package/templates/spec.md +1 -1
package/README.md
CHANGED
|
@@ -1,103 +1,123 @@
|
|
|
1
1
|
# @lininn/openflow
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[中文文档](./README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
OpenSpec + Superpowers workflow orchestrator — bridging requirements specs and engineering execution, eliminating the format gap.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
npm install -g @lininn/openflow
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## Usage
|
|
12
14
|
|
|
13
|
-
###
|
|
15
|
+
### Initialize a project
|
|
14
16
|
|
|
15
17
|
```bash
|
|
16
18
|
cd your-project
|
|
17
19
|
openflow init --tools claude
|
|
18
20
|
```
|
|
19
21
|
|
|
20
|
-
`init`
|
|
21
|
-
1.
|
|
22
|
-
2.
|
|
23
|
-
3.
|
|
24
|
-
4.
|
|
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 openflow skills to `.claude/skills/openflow/`
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
Supported tools: `claude`, `codex`, `cursor` (comma-separated, e.g. `--tools claude,codex`)
|
|
27
29
|
|
|
28
|
-
###
|
|
30
|
+
### Check status
|
|
29
31
|
|
|
30
32
|
```bash
|
|
31
33
|
openflow status
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
Shows dependency installation status and active changes in the project.
|
|
35
37
|
|
|
36
|
-
###
|
|
38
|
+
### Update skills
|
|
37
39
|
|
|
38
40
|
```bash
|
|
39
41
|
openflow update
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
Re-generates project skills after upgrading the npm package.
|
|
43
45
|
|
|
44
|
-
##
|
|
46
|
+
## Workflow Commands
|
|
45
47
|
|
|
46
|
-
|
|
|
47
|
-
|
|
48
|
-
| `/openflow proposal` | proposal |
|
|
49
|
-
| `/openflow brainstorming` | brainstorming |
|
|
50
|
-
| `/openflow spec` | spec |
|
|
51
|
-
| `/openflow build` | build |
|
|
52
|
-
| `/openflow close` | close |
|
|
48
|
+
| Command | Phase | Description |
|
|
49
|
+
|---------|-------|-------------|
|
|
50
|
+
| `/openflow proposal` | proposal | Lightweight capture — 3-5 questions to converge on requirements |
|
|
51
|
+
| `/openflow brainstorming` | brainstorming | Deep design — multi-round tradeoff exploration |
|
|
52
|
+
| `/openflow spec` | spec | Call OpenSpec to generate specs + auto-translate to plan-ready.md |
|
|
53
|
+
| `/openflow build` | build | Call Superpowers to execute implementation |
|
|
54
|
+
| `/openflow close` | close | Verify consistency + archive |
|
|
53
55
|
|
|
54
|
-
##
|
|
56
|
+
## Dependency Strategy
|
|
55
57
|
|
|
56
58
|
```
|
|
57
59
|
Best with: OpenSpec + Superpowers
|
|
58
60
|
Works without them: yes, with manual-file fallback
|
|
59
61
|
```
|
|
60
62
|
|
|
61
|
-
|
|
|
62
|
-
|
|
63
|
-
| OpenSpec | `npm install -g @fission-ai/openspec@latest` |
|
|
64
|
-
| Superpowers | `/plugin install superpowers@claude-plugins-official` |
|
|
63
|
+
| Dependency | Install | Fallback when missing |
|
|
64
|
+
|------------|---------|----------------------|
|
|
65
|
+
| OpenSpec | `npm install -g @fission-ai/openspec@latest` | Manually create `openspec/changes/` directories and files |
|
|
66
|
+
| Superpowers | `/plugin install superpowers@claude-plugins-official` | Manually break down plan-ready.md steps in build phase |
|
|
67
|
+
|
|
68
|
+
### Dual-layer dependency check
|
|
65
69
|
|
|
66
|
-
|
|
70
|
+
| Layer | Mechanism | When missing |
|
|
71
|
+
|-------|-----------|-------------|
|
|
72
|
+
| **Init time** | Detect OpenSpec → auto-install; Detect Superpowers → show install hint | Non-blocking, skills still generated |
|
|
73
|
+
| **Runtime** | Dependency check injected into SKILL.md | Build phase falls back to manual step-by-step execution |
|
|
74
|
+
|
|
75
|
+
## Architecture
|
|
67
76
|
|
|
68
77
|
```
|
|
69
|
-
|
|
78
|
+
User Requirements
|
|
70
79
|
│
|
|
71
|
-
├──
|
|
72
|
-
│
|
|
73
|
-
│
|
|
74
|
-
└──
|
|
75
|
-
|
|
80
|
+
├── Quick ──→ /openflow proposal ──┐
|
|
81
|
+
│ 3-5 questions │
|
|
82
|
+
│ ├─→ proposal.md
|
|
83
|
+
└── Deep ───→ /openflow brainstorming ─┘ (openspec/changes/<name>/)
|
|
84
|
+
Multi-round exploration
|
|
76
85
|
│
|
|
77
86
|
┌──────────▼───────────┐
|
|
78
87
|
│ /openflow spec │
|
|
79
|
-
│ OpenSpec
|
|
88
|
+
│ OpenSpec generates │
|
|
80
89
|
└──────────┬───────────┘
|
|
81
90
|
│
|
|
82
91
|
┌──────────▼───────────┐
|
|
83
|
-
│
|
|
84
|
-
│
|
|
92
|
+
│ Translation Layer │
|
|
93
|
+
│ Requirements → Eng │
|
|
85
94
|
└──────────┬───────────┘
|
|
86
95
|
│
|
|
87
96
|
plan-ready.md
|
|
88
97
|
│
|
|
89
98
|
┌──────────▼───────────┐
|
|
90
99
|
│ /openflow build │
|
|
91
|
-
│ Superpowers
|
|
92
|
-
│ TDD
|
|
100
|
+
│ Superpowers execution │
|
|
101
|
+
│ TDD + checkpoint │
|
|
93
102
|
└──────────┬───────────┘
|
|
94
103
|
│
|
|
95
104
|
┌──────────▼───────────┐
|
|
96
105
|
│ /openflow close │
|
|
97
|
-
│
|
|
106
|
+
│ Verify + archive │
|
|
98
107
|
└──────────────────────┘
|
|
99
108
|
```
|
|
100
109
|
|
|
110
|
+
## Acknowledgments
|
|
111
|
+
|
|
112
|
+
openflow orchestrates two open-source projects:
|
|
113
|
+
|
|
114
|
+
| Project | Repository | License | Usage |
|
|
115
|
+
|---------|-----------|---------|-------|
|
|
116
|
+
| [OpenSpec](https://github.com/Fission-AI/OpenSpec) | `@fission-ai/openspec` | MIT | Generates structured spec files (proposal.md, design.md, specs/, tasks.md). openflow calls its CLI and reads its output format. |
|
|
117
|
+
| [Superpowers](https://github.com/obra/superpowers) | `superpowers` plugin | MIT | Provides `writing-plans` skill for detailed implementation planning. openflow delegates build-phase execution to its workflow. |
|
|
118
|
+
|
|
119
|
+
openflow 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.
|
|
120
|
+
|
|
101
121
|
## License
|
|
102
122
|
|
|
103
123
|
MIT
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# @lininn/openflow
|
|
2
|
+
|
|
3
|
+
[English](./README.md)
|
|
4
|
+
|
|
5
|
+
OpenSpec + Superpowers 工作流协调器,串联需求规格与工程执行,消除格式鸿沟。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @lininn/openflow
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 使用
|
|
14
|
+
|
|
15
|
+
### 初始化项目
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cd your-project
|
|
19
|
+
openflow init --tools claude
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`init` 会自动:
|
|
23
|
+
1. 检测并引导安装 OpenSpec CLI
|
|
24
|
+
2. 检测 Superpowers 并提示安装方式
|
|
25
|
+
3. 检测项目 OpenSpec 初始化状态
|
|
26
|
+
4. 生成 openflow skills 到项目 `.claude/skills/openflow/`
|
|
27
|
+
|
|
28
|
+
支持的工具:`claude`、`codex`、`cursor`(逗号分隔,如 `--tools claude,codex`)
|
|
29
|
+
|
|
30
|
+
### 查看状态
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
openflow status
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
显示依赖安装状态和项目中的活跃变更。
|
|
37
|
+
|
|
38
|
+
### 更新 skills
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
openflow update
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
升级 npm 包后运行,重新生成项目内的 skills 文件。
|
|
45
|
+
|
|
46
|
+
## 工作流命令
|
|
47
|
+
|
|
48
|
+
| 命令 | 阶段 | 说明 |
|
|
49
|
+
|------|------|------|
|
|
50
|
+
| `/openflow proposal` | proposal | 轻量提问,3-5 问快速收敛需求 |
|
|
51
|
+
| `/openflow brainstorming` | brainstorming | 深度设计,多轮方案探索 |
|
|
52
|
+
| `/openflow spec` | spec | 调用 OpenSpec 生成规格 + 自动翻译 |
|
|
53
|
+
| `/openflow build` | build | 调用 Superpowers 执行实现 |
|
|
54
|
+
| `/openflow close` | close | 验证一致性 + 归档 |
|
|
55
|
+
|
|
56
|
+
## 依赖策略
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Best with: OpenSpec + Superpowers
|
|
60
|
+
Works without them: yes, with manual-file fallback
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
| 依赖 | 安装方式 | 缺失时降级 |
|
|
64
|
+
|------|----------|-----------|
|
|
65
|
+
| OpenSpec | `npm install -g @fission-ai/openspec@latest` | 手动创建 `openspec/changes/` 目录和文件 |
|
|
66
|
+
| Superpowers | `/plugin install superpowers@claude-plugins-official` | build 阶段手动拆解 plan-ready.md 步骤执行 |
|
|
67
|
+
|
|
68
|
+
### 双层依赖保障
|
|
69
|
+
|
|
70
|
+
| 层 | 机制 | 缺失时 |
|
|
71
|
+
|----|------|--------|
|
|
72
|
+
| **init 时** | 检测 OpenSpec → 自动安装;检测 Superpowers → 提示安装命令 | 不阻断,继续生成 skills |
|
|
73
|
+
| **运行时** | SKILL.md 注入依赖检测段 | build 阶段降级为手动拆解步骤执行 |
|
|
74
|
+
|
|
75
|
+
## 架构
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
用户需求
|
|
79
|
+
│
|
|
80
|
+
├── 轻量 ──→ /openflow proposal ──┐
|
|
81
|
+
│ 3-5问快速收敛 │
|
|
82
|
+
│ ├─→ proposal.md
|
|
83
|
+
└── 深度 ──→ /openflow brainstorming ─┘ (openspec/changes/<name>/)
|
|
84
|
+
多轮方案探索
|
|
85
|
+
│
|
|
86
|
+
┌──────────▼───────────┐
|
|
87
|
+
│ /openflow spec │
|
|
88
|
+
│ OpenSpec 生成规格 │
|
|
89
|
+
└──────────┬───────────┘
|
|
90
|
+
│
|
|
91
|
+
┌──────────▼───────────┐
|
|
92
|
+
│ 翻译层 (核心) │
|
|
93
|
+
│ 需求视角 → 工程视角 │
|
|
94
|
+
└──────────┬───────────┘
|
|
95
|
+
│
|
|
96
|
+
plan-ready.md
|
|
97
|
+
│
|
|
98
|
+
┌──────────▼───────────┐
|
|
99
|
+
│ /openflow build │
|
|
100
|
+
│ Superpowers 执行 │
|
|
101
|
+
│ TDD 铁律 + 断点恢复 │
|
|
102
|
+
└──────────┬───────────┘
|
|
103
|
+
│
|
|
104
|
+
┌──────────▼───────────┐
|
|
105
|
+
│ /openflow close │
|
|
106
|
+
│ 验证一致性 + 归档 │
|
|
107
|
+
└──────────────────────┘
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 致谢
|
|
111
|
+
|
|
112
|
+
openflow 编排了以下两个开源项目:
|
|
113
|
+
|
|
114
|
+
| 项目 | 仓库 | 许可证 | 使用方式 |
|
|
115
|
+
|------|------|--------|----------|
|
|
116
|
+
| [OpenSpec](https://github.com/Fission-AI/OpenSpec) | `@fission-ai/openspec` | MIT | 生成结构化规格文件(proposal.md、design.md、specs/、tasks.md)。openflow 调用其 CLI 并读取其输出格式。 |
|
|
117
|
+
| [Superpowers](https://github.com/obra/superpowers) | `superpowers` 插件 | MIT | 提供 `writing-plans` skill 用于生成详细实现计划。openflow 在 build 阶段委托其工作流执行。 |
|
|
118
|
+
|
|
119
|
+
openflow 是**独立编排器** — 不捆绑、不分叉、不嵌入任何项目的代码。依赖在 init/运行时检测,任一缺失时降级为手动模式。
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT
|
package/dist/cli/index.js
CHANGED
|
@@ -6,7 +6,7 @@ export function run() {
|
|
|
6
6
|
const program = new Command();
|
|
7
7
|
program
|
|
8
8
|
.name('openflow')
|
|
9
|
-
.description('OpenSpec + Superpowers
|
|
9
|
+
.description('OpenSpec + Superpowers workflow orchestrator')
|
|
10
10
|
.version('0.1.0');
|
|
11
11
|
program.addCommand(initCommand);
|
|
12
12
|
program.addCommand(statusCommand);
|
package/dist/cli/init.js
CHANGED
|
@@ -7,24 +7,24 @@ import { logger } from '../utils/logger.js';
|
|
|
7
7
|
import { exec } from '../utils/shell.js';
|
|
8
8
|
const SUPPORTED_TOOLS = Object.keys(TOOL_PATHS);
|
|
9
9
|
export const initCommand = new Command('init')
|
|
10
|
-
.description('
|
|
11
|
-
.option('-t, --tools <tools>', '
|
|
10
|
+
.description('Initialize openflow skills in the current project')
|
|
11
|
+
.option('-t, --tools <tools>', 'Target tools, comma-separated', 'claude')
|
|
12
12
|
.action(async (options) => {
|
|
13
13
|
const cwd = process.cwd();
|
|
14
14
|
const tools = options.tools.split(',').map((t) => t.trim());
|
|
15
15
|
logger.blank();
|
|
16
|
-
logger.info('openflow init —
|
|
16
|
+
logger.info('openflow init — workflow orchestrator setup');
|
|
17
17
|
logger.blank();
|
|
18
18
|
// Step 1: Check OpenSpec
|
|
19
|
-
logger.step('
|
|
19
|
+
logger.step('Checking OpenSpec ...');
|
|
20
20
|
let depStatus = checkDependencies();
|
|
21
21
|
if (!depStatus.openspec.installed) {
|
|
22
|
-
logger.warn('OpenSpec CLI
|
|
22
|
+
logger.warn('OpenSpec CLI not installed');
|
|
23
23
|
const { installOpenSpec } = await inquirer.prompt([
|
|
24
24
|
{
|
|
25
25
|
type: 'confirm',
|
|
26
26
|
name: 'installOpenSpec',
|
|
27
|
-
message:
|
|
27
|
+
message: `Auto-install? (npm install -g ${DEPS.openspec.npmPkg}@latest)`,
|
|
28
28
|
default: true,
|
|
29
29
|
},
|
|
30
30
|
]);
|
|
@@ -35,49 +35,49 @@ export const initCommand = new Command('init')
|
|
|
35
35
|
depStatus.openspec.autoInstalled = true;
|
|
36
36
|
}
|
|
37
37
|
else {
|
|
38
|
-
logger.warn('
|
|
38
|
+
logger.warn('Skipped OpenSpec install — spec phase will use manual fallback');
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
else {
|
|
42
|
-
logger.success(`OpenSpec CLI
|
|
42
|
+
logger.success(`OpenSpec CLI installed${depStatus.openspec.version ? ` (v${depStatus.openspec.version})` : ''}`);
|
|
43
43
|
}
|
|
44
44
|
// Step 2: Check Superpowers
|
|
45
|
-
logger.step('
|
|
45
|
+
logger.step('Checking Superpowers ...');
|
|
46
46
|
if (!depStatus.superpowers.installed) {
|
|
47
|
-
logger.warn('Superpowers
|
|
47
|
+
logger.warn('Superpowers not installed');
|
|
48
48
|
logger.info(DEPS.superpowers.installHint);
|
|
49
|
-
logger.info('
|
|
49
|
+
logger.info('Re-run openflow init after installing, or build phase will use manual fallback');
|
|
50
50
|
}
|
|
51
51
|
else {
|
|
52
|
-
logger.success('Superpowers
|
|
52
|
+
logger.success('Superpowers installed');
|
|
53
53
|
}
|
|
54
54
|
// Step 3: Check if OpenSpec is initialized in project
|
|
55
|
-
logger.step('
|
|
55
|
+
logger.step('Checking project OpenSpec initialization ...');
|
|
56
56
|
if (!checkOpenSpecInitialized(cwd)) {
|
|
57
57
|
if (depStatus.openspec.installed) {
|
|
58
58
|
const { initOpenSpec } = await inquirer.prompt([
|
|
59
59
|
{
|
|
60
60
|
type: 'confirm',
|
|
61
61
|
name: 'initOpenSpec',
|
|
62
|
-
message: '
|
|
62
|
+
message: 'OpenSpec not initialized in this project. Run openspec init?',
|
|
63
63
|
default: true,
|
|
64
64
|
},
|
|
65
65
|
]);
|
|
66
66
|
if (initOpenSpec) {
|
|
67
67
|
const toolsFlag = tools.map((t) => t).join(',');
|
|
68
68
|
exec(`openspec init --tools ${toolsFlag}`, { stdio: 'inherit' });
|
|
69
|
-
logger.success('OpenSpec
|
|
69
|
+
logger.success('OpenSpec project initialized');
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
else {
|
|
73
|
-
logger.info('
|
|
73
|
+
logger.info('OpenSpec not initialized — directories will be auto-created on first /openflow proposal');
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
else {
|
|
77
|
-
logger.success('OpenSpec
|
|
77
|
+
logger.success('OpenSpec project initialized');
|
|
78
78
|
}
|
|
79
79
|
// Step 4: Generate skills
|
|
80
|
-
logger.step('
|
|
80
|
+
logger.step('Generating openflow skills ...');
|
|
81
81
|
generateSkills({ cwd, tools, depStatus });
|
|
82
82
|
// Step 5: Write state
|
|
83
83
|
writeState(cwd, {
|
|
@@ -88,18 +88,18 @@ export const initCommand = new Command('init')
|
|
|
88
88
|
tools,
|
|
89
89
|
});
|
|
90
90
|
logger.blank();
|
|
91
|
-
logger.success('openflow
|
|
91
|
+
logger.success('openflow initialized!');
|
|
92
92
|
logger.blank();
|
|
93
93
|
if (!depStatus.superpowers.installed) {
|
|
94
|
-
logger.warn('
|
|
95
|
-
logger.info(`
|
|
94
|
+
logger.warn('Note: Superpowers not installed — /openflow build will use manual execution mode');
|
|
95
|
+
logger.info(` Install with: ${DEPS.superpowers.installHint}`);
|
|
96
96
|
logger.blank();
|
|
97
97
|
}
|
|
98
|
-
logger.info('
|
|
99
|
-
logger.info(' /openflow proposal
|
|
100
|
-
logger.info(' /openflow brainstorming
|
|
101
|
-
logger.info(' /openflow spec
|
|
102
|
-
logger.info(' /openflow build
|
|
103
|
-
logger.info(' /openflow close
|
|
98
|
+
logger.info('Available commands:');
|
|
99
|
+
logger.info(' /openflow proposal Quick requirement capture');
|
|
100
|
+
logger.info(' /openflow brainstorming Deep design exploration');
|
|
101
|
+
logger.info(' /openflow spec Generate specs + translate');
|
|
102
|
+
logger.info(' /openflow build Execute implementation');
|
|
103
|
+
logger.info(' /openflow close Verify + archive');
|
|
104
104
|
logger.blank();
|
|
105
105
|
});
|
package/dist/cli/status.js
CHANGED
|
@@ -5,58 +5,57 @@ import { checkDependencies, readState, checkOpenSpecInitialized } from '../core/
|
|
|
5
5
|
import { logger } from '../utils/logger.js';
|
|
6
6
|
import { dirExists } from '../utils/shell.js';
|
|
7
7
|
export const statusCommand = new Command('status')
|
|
8
|
-
.description('
|
|
8
|
+
.description('Show dependency status and active changes')
|
|
9
9
|
.action(() => {
|
|
10
10
|
const cwd = process.cwd();
|
|
11
11
|
logger.blank();
|
|
12
12
|
logger.info('openflow status');
|
|
13
13
|
logger.blank();
|
|
14
14
|
// Dependencies
|
|
15
|
-
logger.step('
|
|
15
|
+
logger.step('Dependencies:');
|
|
16
16
|
const depStatus = checkDependencies();
|
|
17
17
|
if (depStatus.openspec.installed) {
|
|
18
18
|
logger.success(`OpenSpec CLI${depStatus.openspec.version ? ` v${depStatus.openspec.version}` : ''}`);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
|
-
logger.warn('OpenSpec CLI —
|
|
21
|
+
logger.warn('OpenSpec CLI — not installed');
|
|
22
22
|
}
|
|
23
23
|
if (depStatus.superpowers.installed) {
|
|
24
24
|
logger.success('Superpowers');
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
27
|
-
logger.warn('Superpowers —
|
|
27
|
+
logger.warn('Superpowers — not installed (build phase will use manual mode)');
|
|
28
28
|
}
|
|
29
29
|
logger.blank();
|
|
30
30
|
// Project state
|
|
31
|
-
logger.step('
|
|
31
|
+
logger.step('Project:');
|
|
32
32
|
const state = readState(cwd);
|
|
33
33
|
if (state) {
|
|
34
|
-
logger.success(
|
|
35
|
-
logger.info(`
|
|
34
|
+
logger.success(`Initialized (${state.tools.join(', ')})`);
|
|
35
|
+
logger.info(` Created at: ${state.createdAt}`);
|
|
36
36
|
}
|
|
37
37
|
else {
|
|
38
|
-
logger.warn('
|
|
38
|
+
logger.warn('Not initialized — run openflow init');
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
if (checkOpenSpecInitialized(cwd)) {
|
|
42
|
-
logger.success('OpenSpec
|
|
42
|
+
logger.success('OpenSpec project initialized');
|
|
43
43
|
}
|
|
44
44
|
else {
|
|
45
|
-
logger.warn('OpenSpec
|
|
45
|
+
logger.warn('OpenSpec project not initialized');
|
|
46
46
|
}
|
|
47
47
|
logger.blank();
|
|
48
48
|
// Active changes
|
|
49
|
-
logger.step('
|
|
49
|
+
logger.step('Active changes:');
|
|
50
50
|
const changesDir = path.join(cwd, 'openspec', 'changes');
|
|
51
|
-
const archiveDir = path.join(changesDir, 'archive');
|
|
52
51
|
if (!dirExists(changesDir)) {
|
|
53
|
-
logger.info('
|
|
52
|
+
logger.info(' None');
|
|
54
53
|
return;
|
|
55
54
|
}
|
|
56
55
|
const entries = fs.readdirSync(changesDir, { withFileTypes: true })
|
|
57
56
|
.filter((d) => d.isDirectory() && d.name !== 'archive');
|
|
58
57
|
if (entries.length === 0) {
|
|
59
|
-
logger.info('
|
|
58
|
+
logger.info(' None');
|
|
60
59
|
return;
|
|
61
60
|
}
|
|
62
61
|
for (const entry of entries) {
|
package/dist/cli/update.js
CHANGED
|
@@ -3,16 +3,16 @@ import { checkDependencies, readState, writeState, checkOpenSpecInitialized } fr
|
|
|
3
3
|
import { generateSkills } from '../core/skill-generator.js';
|
|
4
4
|
import { logger } from '../utils/logger.js';
|
|
5
5
|
export const updateCommand = new Command('update')
|
|
6
|
-
.description('
|
|
6
|
+
.description('Regenerate openflow skills in the current project')
|
|
7
7
|
.action(() => {
|
|
8
8
|
const cwd = process.cwd();
|
|
9
9
|
const state = readState(cwd);
|
|
10
10
|
if (!state) {
|
|
11
|
-
logger.error('
|
|
11
|
+
logger.error('Project not initialized — run openflow init first');
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
logger.blank();
|
|
15
|
-
logger.info('openflow update —
|
|
15
|
+
logger.info('openflow update — regenerating skills');
|
|
16
16
|
logger.blank();
|
|
17
17
|
const depStatus = checkDependencies();
|
|
18
18
|
generateSkills({
|
|
@@ -27,6 +27,6 @@ export const updateCommand = new Command('update')
|
|
|
27
27
|
openspecProjectInitialized: checkOpenSpecInitialized(cwd),
|
|
28
28
|
});
|
|
29
29
|
logger.blank();
|
|
30
|
-
logger.success('
|
|
30
|
+
logger.success('Skills updated');
|
|
31
31
|
logger.blank();
|
|
32
32
|
});
|
|
@@ -28,14 +28,14 @@ export function checkDependencies() {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
export function tryAutoInstall(pkg) {
|
|
31
|
-
logger.step(
|
|
31
|
+
logger.step(`Installing ${pkg} ...`);
|
|
32
32
|
try {
|
|
33
33
|
execSync(`npm install -g ${pkg}@latest`, { stdio: 'inherit' });
|
|
34
|
-
logger.success(`${pkg}
|
|
34
|
+
logger.success(`${pkg} installed`);
|
|
35
35
|
return true;
|
|
36
36
|
}
|
|
37
37
|
catch {
|
|
38
|
-
logger.error(
|
|
38
|
+
logger.error(`Failed to install ${pkg} — please run manually: npm install -g ${pkg}@latest`);
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -13,11 +13,11 @@ export function generateSkills(options) {
|
|
|
13
13
|
for (const tool of tools) {
|
|
14
14
|
const toolPaths = TOOL_PATHS[tool];
|
|
15
15
|
if (!toolPaths) {
|
|
16
|
-
logger.warn(
|
|
16
|
+
logger.warn(`Unknown tool: ${tool}, skipping`);
|
|
17
17
|
continue;
|
|
18
18
|
}
|
|
19
19
|
const skillsDir = path.join(cwd, toolPaths.skillsDir, SKILL_NAME);
|
|
20
|
-
logger.step(
|
|
20
|
+
logger.step(`Generating ${tool} skills to ${path.relative(cwd, skillsDir)}/`);
|
|
21
21
|
if (!dirExists(skillsDir)) {
|
|
22
22
|
fs.mkdirSync(skillsDir, { recursive: true });
|
|
23
23
|
}
|
|
@@ -28,7 +28,7 @@ export function generateSkills(options) {
|
|
|
28
28
|
for (const phase of phases) {
|
|
29
29
|
generateSkillFile(skillsDir, `${phase}.md`, depStatus);
|
|
30
30
|
}
|
|
31
|
-
logger.success(`${tool} skills
|
|
31
|
+
logger.success(`${tool} skills generated`);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
function generateSkillFile(skillsDir, filename, depStatus) {
|
|
@@ -61,13 +61,13 @@ function injectRuntimeDepCheck(content, depStatus) {
|
|
|
61
61
|
|
|
62
62
|
| 依赖 | 检测方式 | 不可用时 |
|
|
63
63
|
|------|----------|----------|
|
|
64
|
-
| Superpowers writing-plans |
|
|
65
|
-
| OpenSpec CLI |
|
|
64
|
+
| Superpowers writing-plans | \`~/.claude/skills/writing-plans/SKILL.md\` 是否存在 | 降级为手动拆解 plan-ready.md 中的步骤,逐条执行 |
|
|
65
|
+
| OpenSpec CLI | \`openspec\` 命令是否可执行 | 不影响 build 阶段,但 close 阶段归档需手动 mv |
|
|
66
66
|
|
|
67
67
|
如果 Superpowers 不可用,提示用户:
|
|
68
68
|
> "Superpowers 未安装,build 将使用手动执行模式。安装后体验更佳:${DEPS.superpowers.installHint}"
|
|
69
69
|
|
|
70
|
-
如果 Superpowers 可用,调用其
|
|
70
|
+
如果 Superpowers 可用,调用其 \`writing-plans\` skill 生成详细实现计划。
|
|
71
71
|
`;
|
|
72
72
|
// Insert after the first heading
|
|
73
73
|
const lines = content.split('\n');
|
|
@@ -82,7 +82,7 @@ function injectRuntimeDepCheck(content, depStatus) {
|
|
|
82
82
|
}
|
|
83
83
|
function injectSpecRuntimeCheck(content, depStatus) {
|
|
84
84
|
const checkNote = `
|
|
85
|
-
> **OpenSpec 检测**:如果
|
|
85
|
+
> **OpenSpec 检测**:如果 \`openspec\` CLI 可用,调用 \`openspec propose\` 生成完整规格;否则手动根据 proposal.md 生成 design.md + specs/ + tasks.md。
|
|
86
86
|
`;
|
|
87
87
|
const lines = content.split('\n');
|
|
88
88
|
const proposeIdx = lines.findIndex((l) => l.includes('openspec propose'));
|
|
@@ -106,21 +106,21 @@ description: "OpenSpec + Superpowers 工作流协调器。使用 /openflow propo
|
|
|
106
106
|
|
|
107
107
|
| 命令 | 阶段 | 说明 |
|
|
108
108
|
|------|------|------|
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
109
|
+
| \`/openflow proposal\` | proposal | 轻量提问,快速收敛需求 |
|
|
110
|
+
| \`/openflow brainstorming\` | brainstorming | 深度设计,多轮探索 |
|
|
111
|
+
| \`/openflow spec\` | spec | 调用 OpenSpec 生成规格 + 翻译 |
|
|
112
|
+
| \`/openflow build\` | build | 调用 Superpowers 执行实现 |
|
|
113
|
+
| \`/openflow close\` | close | 验证一致性 + 归档 |
|
|
114
114
|
|
|
115
115
|
## 状态检测
|
|
116
116
|
|
|
117
|
-
当用户调用
|
|
117
|
+
当用户调用 \`/openflow\` 不带子命令,或调用某个子命令需要确认前置条件时,执行以下状态检测:
|
|
118
118
|
|
|
119
119
|
| 检查项 | 怎么查 | 结果 |
|
|
120
120
|
|--------|--------|------|
|
|
121
|
-
| 有活跃变更? |
|
|
122
|
-
| 有 plan-ready.md? | 变更目录下是否有
|
|
123
|
-
| 实现已开始? |
|
|
121
|
+
| 有活跃变更? | \`openspec/changes/\` 下是否有非 archive 子目录 | 有→继续 |
|
|
122
|
+
| 有 plan-ready.md? | 变更目录下是否有 \`plan-ready.md\` | 有→看实现状态 |
|
|
123
|
+
| 实现已开始? | \`docs/superpowers/plans/\` 下是否有计划文件 | 有→看是否完成 |
|
|
124
124
|
| 实现已完成? | 计划文件全部 checkbox 已勾选 | 是→close 阶段 |
|
|
125
125
|
|
|
126
126
|
判定结果:
|
|
@@ -134,9 +134,9 @@ description: "OpenSpec + Superpowers 工作流协调器。使用 /openflow propo
|
|
|
134
134
|
|
|
135
135
|
根据子命令或状态检测结果,读取对应阶段文件并执行:
|
|
136
136
|
|
|
137
|
-
1. 如果用户指定了子命令(如
|
|
138
|
-
2. 如果用户只输入
|
|
139
|
-
3.
|
|
137
|
+
1. 如果用户指定了子命令(如 \`/openflow build\`),优先按指定阶段执行,但检查前置条件
|
|
138
|
+
2. 如果用户只输入 \`/openflow\`,执行状态检测,自动路由到对应阶段
|
|
139
|
+
3. 读取阶段文件:\`\${CLAUDE_SKILL_DIR}/<阶段>.md\`
|
|
140
140
|
4. 按阶段文件中的流程执行
|
|
141
141
|
|
|
142
142
|
### 前置条件检查
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
console.log(`
|
|
2
|
-
openflow — OpenSpec + Superpowers
|
|
2
|
+
openflow — OpenSpec + Superpowers workflow orchestrator
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Initialize a project:
|
|
5
5
|
openflow init --tools claude
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Check status:
|
|
8
8
|
openflow status
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Update skills:
|
|
11
11
|
openflow update
|
|
12
12
|
`);
|
package/templates/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: openflow
|
|
3
|
-
description: "OpenSpec + Superpowers
|
|
3
|
+
description: "OpenSpec + Superpowers workflow orchestrator. Use /openflow proposal for quick capture, /openflow brainstorming for deep design, /openflow spec to generate specs + translate, /openflow build to execute, /openflow close to verify and archive. Bridges requirements specs and engineering execution."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# openflow: 工作流协调器
|
package/templates/build.md
CHANGED
package/templates/close.md
CHANGED
package/templates/proposal.md
CHANGED