@kafka0102/onespec 0.1.14 → 0.2.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/assets/skills/onespec/SKILL.md +1 -1
- package/assets/skills/onespec/references/archive.md +32 -9
- package/assets/skills/onespec/references/design.md +20 -18
- package/assets/skills/onespec/references/execute.md +32 -10
- package/assets/skills/onespec/references/fast.md +1 -1
- package/assets/skills/onespec/scripts/onespec-closeout.sh +2 -2
- package/assets/skills-en/onespec/SKILL.md +1 -1
- package/assets/skills-en/onespec/references/archive.md +31 -8
- package/assets/skills-en/onespec/references/design.md +14 -1
- package/assets/skills-en/onespec/references/execute.md +30 -8
- package/assets/skills-en/onespec/references/fast.md +1 -1
- package/package.json +5 -2
- package/src/cli.js +71 -78
- package/src/platforms.js +2 -2
|
@@ -60,7 +60,7 @@ ONESPEC_ENV="${ONESPEC_ENV:-$(find . "$HOME"/.codex "$HOME"/.claude "$HOME"/.cur
|
|
|
60
60
|
- OpenSpec 负责“要做什么”、formal artifacts、approval gate、spec delta 与归档语义。
|
|
61
61
|
- Superpowers 负责高歧义需求澄清、实现计划、TDD、分任务 review 与工程执行质量。
|
|
62
62
|
- 不要询问变更名称。根据任务自动生成简短短横线命名的 `change-id`,如冲突则追加数字。
|
|
63
|
-
- 读取最少必要上下文:`openspec/config.yaml
|
|
63
|
+
- 读取最少必要上下文:`openspec/config.yaml`、相关 `openspec/specs/**`、项目入口文档、当前分支和工作区状态。
|
|
64
64
|
- 只问会改变 proposal、执行路径、分支处理或归档结果的问题。
|
|
65
65
|
- 当共同规则与阶段规则冲突时,以当前阶段 reference 的停止条件为准。
|
|
66
66
|
- 每个阶段 reference 定义了强制暂停 gate(如 `references/execute.md` 的“实现完成 Gate”、`references/design.md` 的“批准 Gate”)。路由进入下一阶段前,必须确认上一阶段的 gate 已完成。如果 gate 未完成就试图进入下一阶段,必须拒绝并指出缺失步骤。
|
|
@@ -34,13 +34,26 @@ ONESPEC_ENV="${ONESPEC_ENV:-$(find . "$HOME"/.codex "$HOME"/.claude "$HOME"/.cur
|
|
|
34
34
|
|
|
35
35
|
入口校验:如果 phase 已到 `review`,但 `.onespec.yaml` 里的 `handoff_purpose` 不是 `review`,或 `handoff_hash` 为空,说明 execute gate 可能未正常完成。此时必须告诉用户:"执行阶段的 review handoff 状态未写回,建议先回到执行阶段补充汇报(回复 `补充汇报` 或重新触发 execute gate)。" 不允许静默跳过。
|
|
36
36
|
|
|
37
|
+
### 1.1 用户确认请求规则
|
|
38
|
+
|
|
39
|
+
当归档阶段需要用户确认归档、合并、废弃 worktree、继续修改或停留评审时,必须把“需要用户选择”作为独立块输出,标题固定为 `用户确认请求`。不要把当前状态、推荐收尾动作和等待用户确认混成同一段。
|
|
40
|
+
|
|
41
|
+
确认块必须包含:
|
|
42
|
+
|
|
43
|
+
- 一句明确指令:`请回复编号。`
|
|
44
|
+
- 1-3 个编号选项,其中第 1 项通常是推荐项,并标注“推荐”
|
|
45
|
+
- `其他:` 说明非编号内容如何处理,通常视为继续修改当前实现
|
|
46
|
+
- 如果用户补充了新条件但还没有形成明确选择,继续给出新的编号选项,直到用户明确选择、终止或要求继续往下走
|
|
47
|
+
|
|
48
|
+
如果平台提供结构化询问能力,例如 `ask user questions`、`request_user_input` 或等价 UI,优先用结构化询问承载这些编号选项;如果当前环境没有这类能力,则在普通消息中输出上述 `用户确认请求` 块。无论使用哪种形式,都不能只给一句“建议归档”或“下一步进入收尾”就结束。
|
|
49
|
+
|
|
37
50
|
## 2. 用户评审
|
|
38
51
|
|
|
39
52
|
实现完成后让用户评审。若用户指出问题,继续修改并重新验证。
|
|
40
53
|
|
|
41
54
|
开发完成后不需要再次让用户确认是否 review,也不需要展示常规“继续评审 / 保留分支”类选项。收尾应先处理临时 worktree 中的代码去向;如果用户回复任意非编号内容,默认视为“继续修改当前实现”,直接回到代码处理环节。
|
|
42
55
|
|
|
43
|
-
不要让用户自己猜“下一步该输入什么”。如果用户是直接进入 archive phase
|
|
56
|
+
不要让用户自己猜“下一步该输入什么”。如果用户是直接进入 archive phase,尚未做收尾选择,则必须给出用户只需回复数字编号的选项。
|
|
44
57
|
|
|
45
58
|
如果用户是从 execute phase 的完成汇报进入这里,并且已经回复了收尾编号,则把那次回复视为唯一有效授权,不得再次展示一轮相同菜单,也不得再追加“是否处理合并/归档”之类的中间确认。此时只需汇报必要状态检查,并按用户已选动作直接执行,不需要拆成两轮确认。
|
|
46
59
|
|
|
@@ -53,12 +66,22 @@ ONESPEC_ENV="${ONESPEC_ENV:-$(find . "$HOME"/.codex "$HOME"/.claude "$HOME"/.cur
|
|
|
53
66
|
|
|
54
67
|
如果当前分支或工作区不同于 `origin_*`,必须明确说明“你当前看到的是临时实现分支或临时 worktree”。如果用户改为输入任意非编号内容,则表示当前功能还有问题,需要继续修改。
|
|
55
68
|
|
|
56
|
-
|
|
69
|
+
可选收尾路径必须先按当前是否临时 worktree 差异化判断,不允许凭感觉直接给固定菜单。先执行:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
"$ONESPEC_BASH" "$ONESPEC_CLOSEOUT" recommend-actions <change-id>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
如果 `temporary_worktree: true`,可选收尾路径只有以下三种:
|
|
57
76
|
|
|
58
77
|
- 归档当前 change,并合并分支到 base 分支
|
|
59
78
|
- 直接归档,不合并到 base 分支
|
|
60
79
|
- 删除当前临时 worktree并废弃代码
|
|
61
80
|
|
|
81
|
+
如果 `temporary_worktree: false`,可选收尾路径只有一种:
|
|
82
|
+
|
|
83
|
+
- 直接归档(不合并分支,不删除 worktree)
|
|
84
|
+
|
|
62
85
|
合并、废弃、删除与归档都是有后果的操作;但只要用户已经在编号菜单里明确授权,就直接执行,不要再拆成二次确认。
|
|
63
86
|
|
|
64
87
|
## 2.1 Superpowers Worktree 优先规则
|
|
@@ -79,9 +102,9 @@ ONESPEC_ENV="${ONESPEC_ENV:-$(find . "$HOME"/.codex "$HOME"/.claude "$HOME"/.cur
|
|
|
79
102
|
3. 如果用户只需要保留归档记录而不合并代码,则允许“仅归档”。
|
|
80
103
|
4. 如果用户要废弃代码,则删除 worktree 并丢弃本地临时分支。
|
|
81
104
|
|
|
82
|
-
## 2.2
|
|
105
|
+
## 2.2 差异化收尾规则
|
|
83
106
|
|
|
84
|
-
|
|
107
|
+
如果脚本探测到 `temporary_worktree: true`,必须展示以下编号菜单:
|
|
85
108
|
|
|
86
109
|
```text
|
|
87
110
|
1. 归档当前 change,并合并分支到 base 分支
|
|
@@ -99,14 +122,14 @@ ONESPEC_ENV="${ONESPEC_ENV:-$(find . "$HOME"/.codex "$HOME"/.claude "$HOME"/.cur
|
|
|
99
122
|
|
|
100
123
|
如果当前不是临时 worktree,且代码已经真正位于目标分支,也允许执行 `archive-only`。
|
|
101
124
|
|
|
102
|
-
|
|
125
|
+
如果脚本探测到 `temporary_worktree: false`,说明代码已经真正位于目标分支/目标工作区。无论当前目标分支是否为 `main`/`master`,都不要再展示“归档后合并”或“删除当前临时 worktree”两个选项。此时收尾菜单只保留一个编号:
|
|
103
126
|
|
|
104
127
|
```text
|
|
105
|
-
1.
|
|
128
|
+
1. 直接归档(当前不在临时 worktree,无需额外合并分支或删除 worktree)
|
|
106
129
|
其他:任意非编号内容视为继续修改当前实现;用户未输入时默认停留在当前评审阶段
|
|
107
130
|
```
|
|
108
131
|
|
|
109
|
-
|
|
132
|
+
也就是说,不在临时 worktree 时,不管当前目标分支叫 `main`、`master`、`develop`、`feature/*` 还是其他名称,都不要提示合并分支/删除 worktree。
|
|
110
133
|
|
|
111
134
|
如果用户之前已经在 execute phase 的完成菜单里选了收尾编号,则这里不再重复相同菜单,而是结合实际工作区状态直接执行对应动作。
|
|
112
135
|
|
|
@@ -141,8 +164,8 @@ ONESPEC_ENV="${ONESPEC_ENV:-$(find . "$HOME"/.codex "$HOME"/.claude "$HOME"/.cur
|
|
|
141
164
|
1. closeout 前先自动提交当前工作区里与本次 change 相关的脏文件。
|
|
142
165
|
2. 如果 archive 产生了新的归档工件或删除了 `.onespec.yaml`,archive 之后再自动补一笔归档提交。
|
|
143
166
|
3. 如果用户选择“先归档再合并”,则必须在 archive 提交完成后,再把当前实现分支合并回 base 分支。
|
|
144
|
-
- 如果用户选择 `archive-then-merge-worktree
|
|
145
|
-
- 如果用户选择 `archive-only`,直接执行 OpenSpec archive,并将状态设为 `archived
|
|
167
|
+
- 如果用户选择 `archive-then-merge-worktree`,必须仅在 `temporary_worktree: true` 时执行;先归档,再合并到目标分支,最后删除临时 worktree,并将状态设为 `archived`。
|
|
168
|
+
- 如果用户选择 `archive-only`,直接执行 OpenSpec archive,并将状态设为 `archived`;不自动合并。若 `temporary_worktree: false`,也不得删除工作区或 worktree。
|
|
146
169
|
- 如果用户选择 `discard-worktree`,不执行归档,不把废弃分支代码合入 base 分支。
|
|
147
170
|
- 只有真正执行 archive 后,才删除运行时状态文件:
|
|
148
171
|
|
|
@@ -22,7 +22,7 @@ ONESPEC_ENV="${ONESPEC_ENV:-$(find . "$HOME"/.codex "$HOME"/.claude "$HOME"/.cur
|
|
|
22
22
|
|
|
23
23
|
读取最少必要上下文:
|
|
24
24
|
|
|
25
|
-
- `openspec/config.yaml`、`openspec/
|
|
25
|
+
- `openspec/config.yaml`、`openspec/specs/**` 中与任务相关的部分
|
|
26
26
|
- 项目入口文档,如 `AGENTS.md`、`README.md`、`docs/**` 中与任务相关的部分
|
|
27
27
|
- 当前分支和工作区状态
|
|
28
28
|
|
|
@@ -138,11 +138,24 @@ OpenSpec artifacts 写完后,不要只汇报“proposal 已生成”。必须
|
|
|
138
138
|
- `Superpowers + subagent + current worktree/current branch`
|
|
139
139
|
- 用户可覆盖推荐
|
|
140
140
|
|
|
141
|
+
### 3.1 用户确认请求规则
|
|
142
|
+
|
|
143
|
+
当输出结果后需要用户决定是否批准、是否进入实现、是否改路径或是否继续停留时,必须把“需要用户选择”作为独立块输出,标题固定为 `用户确认请求`。不要把结论、推荐意见和等待用户确认混成同一段。
|
|
144
|
+
|
|
145
|
+
确认块必须包含:
|
|
146
|
+
|
|
147
|
+
- 一句明确指令:`请回复编号。`
|
|
148
|
+
- 2-4 个编号选项,其中第 1 项通常是推荐项,并标注“推荐”
|
|
149
|
+
- `其他:` 说明用户可以补充条件或提出不在菜单中的操作
|
|
150
|
+
- 如果用户补充了新条件但还没有形成明确选择,继续给出新的编号选项,直到用户明确选择、终止或要求继续往下走
|
|
151
|
+
|
|
152
|
+
如果平台提供结构化询问能力,例如 `ask user questions`、`request_user_input` 或等价 UI,优先用结构化询问承载这些编号选项;如果当前环境没有这类能力,则在普通消息中输出上述 `用户确认请求` 块。无论使用哪种形式,都不能只给一句“推荐使用某路径”就结束。
|
|
153
|
+
|
|
141
154
|
## 4. Proposal 批准 Gate 与路径选择
|
|
142
155
|
|
|
143
156
|
默认意图映射、issue workflow 路由或实现路径推荐,不等于 proposal 已获批。
|
|
144
157
|
|
|
145
|
-
只有用户明确批准 proposal / design / spec
|
|
158
|
+
只有用户明确批准 proposal / design / spec 后,才允许进入实现计划。设计阶段结束时,不要只给一句自由文本,也不要要求用户输入 `批准`、`yes`、`continue` 等完整词;必须给出“显式编号选项 + 推荐项”菜单。用户只需回复数字编号。沉默、“看起来还行”、最初的“开始实现”、“执行这个 change”或“make plan”都不算对 proposal 产物的批准。
|
|
146
159
|
|
|
147
160
|
生成批准菜单前先确定推荐组合:
|
|
148
161
|
|
|
@@ -155,42 +168,31 @@ OpenSpec artifacts 写完后,不要只汇报“proposal 已生成”。必须
|
|
|
155
168
|
默认使用下面这组批准菜单,并把推荐组合写进第 1 项。菜单必须解释组合由三部分构成:实现路径 + 执行方式 + 工作区策略。
|
|
156
169
|
|
|
157
170
|
1. 批准当前 proposal / design / spec,并按推荐组合继续实现:`<recommended-combination>`(推荐)
|
|
158
|
-
可直接回复:`批准,按推荐路径继续`
|
|
159
171
|
2. 批准当前 proposal / design / spec,但我要改实现路径、执行方式或工作区
|
|
160
|
-
可直接回复:`批准,但我要改实现路径`
|
|
161
172
|
3. 先修改 proposal / design / tasks / spec;我会补充要改的点
|
|
162
|
-
可直接回复:`先修改 proposal`
|
|
163
173
|
4. 先停在设计阶段,暂不进入实现
|
|
164
|
-
可直接回复:`先停在设计阶段`
|
|
165
174
|
其他:如果意图不在以上选项里,允许用户直接补充说明其他操作
|
|
166
175
|
|
|
167
176
|
菜单解释规则:
|
|
168
177
|
|
|
169
|
-
- 用户回复 `1
|
|
170
|
-
- 用户回复 `2
|
|
171
|
-
- 用户回复 `3
|
|
172
|
-
- 用户回复 `4
|
|
178
|
+
- 用户回复 `1`:视为批准当前 artifacts,并接受当前推荐组合;不要再二次询问 `subagent/local` 或 `worktree/current-branch`,直接记录该组合对应的 `implementation_path`、`execution_method` 与 `workspace`。
|
|
179
|
+
- 用户回复 `2`:视为批准当前 artifacts,但要覆盖推荐组合;此时继续给出组合菜单,不要把 `subagent/local` 与 `worktree/current-branch` 拆成两轮问题。
|
|
180
|
+
- 用户回复 `3`:继续留在 design phase,根据用户反馈修改 artifacts,不进入实现。
|
|
181
|
+
- 用户回复 `4`:暂停在设计阶段,等待用户后续指令。
|
|
173
182
|
- 用户输入其他自由文本:如果意图清晰,按用户自定义意图处理;如果仍有歧义,只追问一个最短的澄清问题。
|
|
174
183
|
|
|
175
|
-
当用户选择第 2
|
|
184
|
+
当用户选择第 2 项,后续确认也使用“显式编号组合选项 + 推荐项”菜单;用户只需回复数字编号。不要只给一句自由文本,也不要在每个选项下附加口令提示。根据当前是否已经在附加 worktree 中生成菜单:
|
|
176
185
|
|
|
177
186
|
- 如果当前不在附加 worktree 中,默认菜单:
|
|
178
187
|
1. `Superpowers + subagent + new worktree`(推荐)
|
|
179
|
-
可直接回复:`使用 Superpowers subagent worktree`
|
|
180
188
|
2. `Superpowers + local + new worktree`
|
|
181
|
-
可直接回复:`使用 Superpowers local worktree`
|
|
182
189
|
3. `Superpowers + local + current branch`
|
|
183
|
-
可直接回复:`使用 Superpowers local current-branch`
|
|
184
190
|
4. `OpenSpec apply + native + current branch`
|
|
185
|
-
可直接回复:`使用 OpenSpec apply`
|
|
186
191
|
其他:允许用户补充说明特殊组合;例如明确要求 `Superpowers + subagent + current branch`
|
|
187
192
|
- 如果当前已经在附加 worktree 中,默认菜单:
|
|
188
193
|
1. `Superpowers + subagent + current worktree/current branch`(推荐)
|
|
189
|
-
可直接回复:`使用 Superpowers subagent 当前 worktree`
|
|
190
194
|
2. `Superpowers + local + current worktree/current branch`
|
|
191
|
-
可直接回复:`使用 Superpowers local 当前 worktree`
|
|
192
195
|
3. `OpenSpec apply + native + current worktree/current branch`
|
|
193
|
-
可直接回复:`使用 OpenSpec apply`
|
|
194
196
|
其他:允许用户补充说明特殊组合;不要推荐再创建新的 worktree
|
|
195
197
|
|
|
196
198
|
`main`/`master` 规则:
|
|
@@ -36,6 +36,19 @@ apply 前至少读取:
|
|
|
36
36
|
|
|
37
37
|
如果 proposal 尚未批准,直接停止,不要开始实现。
|
|
38
38
|
|
|
39
|
+
### 1.1 用户确认请求规则
|
|
40
|
+
|
|
41
|
+
当执行阶段需要用户确认实现路径、工作区策略、继续实现、回到设计修订或完成后的收尾动作时,必须把“需要用户选择”作为独立块输出,标题固定为 `用户确认请求`。不要把结论、验证结果、推荐意见和等待用户确认混成同一段。
|
|
42
|
+
|
|
43
|
+
确认块必须包含:
|
|
44
|
+
|
|
45
|
+
- 一句明确指令:`请回复编号。`
|
|
46
|
+
- 2-6 个编号选项,其中第 1 项通常是推荐项,并标注“推荐”
|
|
47
|
+
- `其他:` 说明非编号内容如何处理,通常视为继续修改当前实现或补充特殊条件
|
|
48
|
+
- 如果用户补充了新条件但还没有形成明确选择,继续给出新的编号选项,直到用户明确选择、终止或要求继续往下走
|
|
49
|
+
|
|
50
|
+
如果平台提供结构化询问能力,例如 `ask user questions`、`request_user_input` 或等价 UI,优先用结构化询问承载这些编号选项;如果当前环境没有这类能力,则在普通消息中输出上述 `用户确认请求` 块。无论使用哪种形式,都不能只给一句“下一步应进入某阶段”或“推荐使用某路径”就结束。
|
|
51
|
+
|
|
39
52
|
如果 proposal 阶段已经确认实现路径:
|
|
40
53
|
|
|
41
54
|
- 用户确认 `Superpowers`:继续 Superpowers Make Plan。
|
|
@@ -210,11 +223,19 @@ git -C "$implementation_workspace_path" status --short
|
|
|
210
223
|
7. 是否更新了 `proposal.md`、`design.md` 或 spec delta
|
|
211
224
|
8. 测试结果
|
|
212
225
|
9. `openspec validate <change-id> --strict` 结果
|
|
213
|
-
10.
|
|
226
|
+
10. 下一步编号选项(必须给出只需回复数字编号的菜单,并明确任意非编号内容视为继续修改当前实现)
|
|
214
227
|
|
|
215
228
|
### 5.3 下一步编号菜单模板
|
|
216
229
|
|
|
217
|
-
|
|
230
|
+
生成下一步菜单前,必须先用脚本探测当前收尾状态;不要凭分支名、路径命名或主观判断推断是否需要合并/删除 worktree:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
"$ONESPEC_BASH" "$ONESPEC_CLOSEOUT" recommend-actions <change-id>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
菜单必须按探测结果差异化生成:
|
|
237
|
+
|
|
238
|
+
- 如果 `temporary_worktree: true`,说明当前实现位于临时 worktree。汇报结尾必须包含以下格式的编号提示(可微调措辞,但结构和编号语义不可省略):
|
|
218
239
|
|
|
219
240
|
```
|
|
220
241
|
---
|
|
@@ -231,7 +252,7 @@ git -C "$implementation_workspace_path" status --short
|
|
|
231
252
|
---
|
|
232
253
|
```
|
|
233
254
|
|
|
234
|
-
|
|
255
|
+
- 如果 `temporary_worktree: false`,说明当前实现已经在目标分支/目标工作区,不存在可合并回收的临时 worktree。无论该分支是否为 `main`/`master`,都不要提示“合并分支到 base 分支”或“删除当前临时 worktree”。此时收尾菜单必须收缩为仅归档一个选项:
|
|
235
256
|
|
|
236
257
|
```
|
|
237
258
|
---
|
|
@@ -241,20 +262,21 @@ git -C "$implementation_workspace_path" status --short
|
|
|
241
262
|
📍 当前工作区: `<path>`
|
|
242
263
|
📍 origin: `<origin_branch>` @ `<origin_workspace_path>`
|
|
243
264
|
|
|
244
|
-
1.
|
|
265
|
+
1. 直接归档(当前不在临时 worktree,无需额外合并分支或删除 worktree)
|
|
245
266
|
其他:任意非编号内容视为继续修改当前实现;用户未输入时默认停留在当前评审阶段
|
|
246
267
|
---
|
|
247
268
|
```
|
|
248
269
|
|
|
249
|
-
|
|
270
|
+
也就是说,不在临时 worktree 时,不管当前目标分支叫 `main`、`master`、`develop`、`feature/*` 还是其他名称,都不要提示合并分支/删除 worktree。
|
|
250
271
|
|
|
251
|
-
|
|
272
|
+
如果脚本探测到当前分支或工作区不同于 `origin_*`,还必须额外说明:"当前实现位于临时分支或临时 worktree;若你直接回复非编号内容,我会按继续修改处理。"
|
|
252
273
|
|
|
253
|
-
-
|
|
254
|
-
-
|
|
255
|
-
-
|
|
274
|
+
- `temporary_worktree: true` 且选择 `1` 时,archive phase 必须按“先归档,再合并分支到 base 分支,最后删除临时 worktree”的固定顺序执行。
|
|
275
|
+
- `temporary_worktree: true` 且选择 `2` 时,archive phase 只做归档,不合并分支,也不自动删除当前 worktree。
|
|
276
|
+
- `temporary_worktree: true` 且选择 `3` 时,archive phase 删除当前临时 worktree 并废弃代码,不执行归档。
|
|
277
|
+
- `temporary_worktree: false` 且选择 `1` 时,archive phase 只做归档;不得合并分支,不得删除工作区或 worktree。
|
|
256
278
|
|
|
257
|
-
不要只停在“下一步应进入 archive phase”这种抽象提示,也不要只说“做 `review-closeout
|
|
279
|
+
不要只停在“下一步应进入 archive phase”这种抽象提示,也不要只说“做 `review-closeout`”。必须同时给出用户只需回复数字编号的选项。
|
|
258
280
|
|
|
259
281
|
### 5.4 反模式(NEVER)
|
|
260
282
|
|
|
@@ -24,7 +24,7 @@ ONESPEC_ENV="${ONESPEC_ENV:-$(find . "$HOME"/.codex "$HOME"/.claude "$HOME"/.cur
|
|
|
24
24
|
|
|
25
25
|
- 仅在用户明确要求 `onespec-fast`、快速路径、fast apply、OpenSpec 自动 proposal/开发/归档或自动贯通时使用。
|
|
26
26
|
- 不要询问 change 名称。根据任务自动生成简短短横线命名的 `change-id`,如冲突则追加数字。
|
|
27
|
-
- 读取最少必要上下文:`openspec/config.yaml
|
|
27
|
+
- 读取最少必要上下文:`openspec/config.yaml`、相关 `openspec/specs/**`、项目入口文档、当前分支和工作区状态。
|
|
28
28
|
- 只有 OpenSpec 必需上下文缺失到无法写出有效 proposal、或项目文档明确禁止自动修改当前分支时才暂停。
|
|
29
29
|
|
|
30
30
|
## 2. 直接 Proposal
|
|
@@ -271,8 +271,8 @@ cmd_validate_actions() {
|
|
|
271
271
|
elif [ "$has_discard_worktree" = "true" ]; then
|
|
272
272
|
message="允许删除临时 worktree 并废弃对应本地分支代码;废弃后不归档。"
|
|
273
273
|
elif [ "$has_archive_only" = "true" ]; then
|
|
274
|
-
if [ "$temporary" != "true" ]
|
|
275
|
-
message="允许直接归档当前 change
|
|
274
|
+
if [ "$temporary" != "true" ]; then
|
|
275
|
+
message="允许直接归档当前 change;当前不在临时 worktree,当前分支 ${current_head} 已是目标分支,无需额外合并分支,也不会删除工作区。"
|
|
276
276
|
else
|
|
277
277
|
message="允许直接归档当前 change,不合并到 base 分支,也不自动删除当前 worktree。"
|
|
278
278
|
fi
|
|
@@ -60,7 +60,7 @@ Default intent mapping:
|
|
|
60
60
|
- OpenSpec owns scope, formal artifacts, approval gates, spec deltas, and archive semantics.
|
|
61
61
|
- Superpowers owns high-ambiguity clarification, implementation planning, TDD, per-task review, and execution quality.
|
|
62
62
|
- Do not ask the user to name the change. Generate a short kebab-case `change-id` from the task and append a suffix if needed.
|
|
63
|
-
- Read the minimum necessary context: `openspec/config.yaml`,
|
|
63
|
+
- Read the minimum necessary context: `openspec/config.yaml`, relevant `openspec/specs/**`, project entry docs, and current branch/worktree state.
|
|
64
64
|
- Only ask questions that can change the proposal, execution path, branch handling, or archive result.
|
|
65
65
|
- If shared and phase-specific rules conflict, the current phase reference wins.
|
|
66
66
|
- Each phase reference defines mandatory pause gates, such as the approval gate in `references/design.md` and the implementation-complete gate in `references/execute.md`. Before routing to the next phase, confirm the previous gate is complete; if it is not, refuse to continue and name the missing gate.
|
|
@@ -34,6 +34,19 @@ If state has not reached `review`, explain what is still missing: implementation
|
|
|
34
34
|
|
|
35
35
|
Entry validation: if phase is already `review` but `.onespec.yaml` does not show `handoff_purpose: review` or does not have a `handoff_hash`, treat that as an incomplete execute gate. Tell the user the review handoff state was not written back and send them to re-run the execute report instead of silently continuing.
|
|
36
36
|
|
|
37
|
+
### 1.1 User Confirmation Request Rules
|
|
38
|
+
|
|
39
|
+
When archive phase requires the user to confirm archive, merge, discard-worktree, continued implementation, or staying in review, render "user choice required" as a standalone block titled `User Confirmation Request`. Do not mix current state, recommended closeout action, and pending confirmation into one paragraph.
|
|
40
|
+
|
|
41
|
+
The confirmation block must include:
|
|
42
|
+
|
|
43
|
+
- one explicit instruction: `Reply with a number.`
|
|
44
|
+
- 1-3 numbered options, with item 1 usually marked as `Recommended`
|
|
45
|
+
- `Other:` explaining how non-numbered content will be handled, usually as continued implementation work
|
|
46
|
+
- if the user adds constraints but still has not made a clear choice, continue presenting updated numbered options until the user chooses, stops, or explicitly tells you to continue
|
|
47
|
+
|
|
48
|
+
If the platform provides structured question UI such as `ask user questions`, `request_user_input`, or an equivalent mechanism, prefer that for these numbered options. If no such mechanism is available, render the `User Confirmation Request` block in the normal message. In either form, do not end with only a sentence like "archive is recommended" or "the next step is closeout."
|
|
49
|
+
|
|
37
50
|
## 2. User Review
|
|
38
51
|
|
|
39
52
|
Let the user review the implementation. If they raise issues, continue editing and re-verify.
|
|
@@ -53,12 +66,22 @@ Before offering closeout choices, explicitly tell the user:
|
|
|
53
66
|
|
|
54
67
|
If the current branch or workspace differs from the recorded `origin_*` fields, explicitly say that the implementation is now living in a temporary branch or temporary worktree. If the user switches to free-form text, treat it as a request for more code changes.
|
|
55
68
|
|
|
56
|
-
Supported closeout paths
|
|
69
|
+
Supported closeout paths must first be selected from the actual temporary-worktree state. Do not show a fixed menu by intuition. First run:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
"$ONESPEC_BASH" "$ONESPEC_CLOSEOUT" recommend-actions <change-id>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
If `temporary_worktree: true`, supported closeout paths are limited to these three outcomes:
|
|
57
76
|
|
|
58
77
|
- Archive the current change, then merge the branch into the base branch
|
|
59
78
|
- Archive only, without merging
|
|
60
79
|
- Delete the current temporary worktree and discard the code
|
|
61
80
|
|
|
81
|
+
If `temporary_worktree: false`, the only supported closeout path is:
|
|
82
|
+
|
|
83
|
+
- Archive only, without merging or deleting a worktree
|
|
84
|
+
|
|
62
85
|
Merge, discard, deletion, and archive are consequential actions, but once the user has explicitly selected them in the numbered menu, execute them directly without another confirmation round.
|
|
63
86
|
|
|
64
87
|
## 2.1 Superpowers Worktree Priority
|
|
@@ -79,9 +102,9 @@ Default recommended order:
|
|
|
79
102
|
3. if the user only wants to preserve the archive record without merging code, allow archive-only
|
|
80
103
|
4. if the user wants to discard the code, delete the worktree and drop the local temporary branch
|
|
81
104
|
|
|
82
|
-
## 2.2
|
|
105
|
+
## 2.2 State-Specific Closeout Rules
|
|
83
106
|
|
|
84
|
-
If the
|
|
107
|
+
If the script reports `temporary_worktree: true`, show this menu:
|
|
85
108
|
|
|
86
109
|
```text
|
|
87
110
|
1. Archive the current change, then merge the branch into the base branch
|
|
@@ -99,14 +122,14 @@ Menu interpretation:
|
|
|
99
122
|
|
|
100
123
|
If the current workspace is not a temporary worktree and the code is already truly on the target branch, `archive-only` is allowed.
|
|
101
124
|
|
|
102
|
-
If the
|
|
125
|
+
If the script reports `temporary_worktree: false`, the code is already truly on the target branch/workspace. Regardless of whether the target branch is `main`, `master`, `develop`, `feature/*`, or any other name, do not show the "archive then merge" or "delete the current temporary worktree" options. In that case the closeout menu must contain only:
|
|
103
126
|
|
|
104
127
|
```text
|
|
105
|
-
1. Archive only
|
|
128
|
+
1. Archive only (current checkout is not a temporary worktree; no branch merge or worktree deletion is needed)
|
|
106
129
|
Other: any non-numbered content means continue modifying the current implementation; if the user gives no input, remain paused in the current review stage
|
|
107
130
|
```
|
|
108
131
|
|
|
109
|
-
In other words,
|
|
132
|
+
In other words, when `temporary_worktree: false`, do not prompt for branch merge or worktree deletion on any target branch.
|
|
110
133
|
|
|
111
134
|
If the user already selected a closeout number in the execute phase completion menu, do not repeat the same menu here; combine that reply with the actual workspace state and execute the matching action directly.
|
|
112
135
|
|
|
@@ -141,8 +164,8 @@ Before merge, discard, delete, or archive is finalized, always check whether the
|
|
|
141
164
|
1. auto-commit current-workspace dirty files related to the change before closeout continues
|
|
142
165
|
2. if archive creates new archive artifacts or removes `.onespec.yaml`, auto-commit the archive result after archive finishes
|
|
143
166
|
3. if the user chooses archive-then-merge, merge the implementation branch back into the base branch only after the archive commit is complete
|
|
144
|
-
- If the user selects `archive-then-merge-worktree`, archive first, then merge into the target branch, and set state to `archived`.
|
|
145
|
-
- If the user selects `archive-only`, run OpenSpec archive and set state to `archived`; do not auto-merge
|
|
167
|
+
- If the user selects `archive-then-merge-worktree`, run it only when `temporary_worktree: true`; archive first, then merge into the target branch, then delete the temporary worktree, and set state to `archived`.
|
|
168
|
+
- If the user selects `archive-only`, run OpenSpec archive and set state to `archived`; do not auto-merge. When `temporary_worktree: false`, also do not delete any workspace or worktree.
|
|
146
169
|
- If the user discards the worktree, do not archive and do not merge discarded branch code into the base branch.
|
|
147
170
|
- Only after archive actually runs should the runtime state file be removed:
|
|
148
171
|
|
|
@@ -22,7 +22,7 @@ Treat `recover` output as the current phase contract, not as reference informati
|
|
|
22
22
|
|
|
23
23
|
Read the minimum necessary context:
|
|
24
24
|
|
|
25
|
-
- Relevant parts of `openspec/config.yaml
|
|
25
|
+
- Relevant parts of `openspec/config.yaml` and `openspec/specs/**`
|
|
26
26
|
- Relevant project entry docs such as `AGENTS.md`, `README.md`, or `docs/**`
|
|
27
27
|
- Current branch and workspace state
|
|
28
28
|
|
|
@@ -138,6 +138,19 @@ Always state:
|
|
|
138
138
|
- `Superpowers + subagent + current worktree/current branch`
|
|
139
139
|
- that the user may override the recommendation
|
|
140
140
|
|
|
141
|
+
### 3.1 User Confirmation Request Rules
|
|
142
|
+
|
|
143
|
+
When the result requires the user to decide whether to approve, start implementation, change the path, or stay in design, render "user choice required" as a standalone block titled `User Confirmation Request`. Do not mix the conclusion, recommendation, and pending confirmation into one paragraph.
|
|
144
|
+
|
|
145
|
+
The confirmation block must include:
|
|
146
|
+
|
|
147
|
+
- one explicit instruction: `Reply with a number.`
|
|
148
|
+
- 2-4 numbered options, with item 1 usually marked as `Recommended`
|
|
149
|
+
- `Other:` explaining that the user may add constraints or request an operation not listed
|
|
150
|
+
- if the user adds constraints but still has not made a clear choice, continue presenting updated numbered options until the user chooses, stops, or explicitly tells you to continue
|
|
151
|
+
|
|
152
|
+
If the platform provides structured question UI such as `ask user questions`, `request_user_input`, or an equivalent mechanism, prefer that for these numbered options. If no such mechanism is available, render the `User Confirmation Request` block in the normal message. In either form, do not end with only a sentence like "I recommend this path."
|
|
153
|
+
|
|
141
154
|
## 4. Proposal Approval Gate and Path Selection
|
|
142
155
|
|
|
143
156
|
Default intent mapping, issue-workflow routing, or implementation recommendations do not count as proposal approval.
|
|
@@ -36,6 +36,19 @@ Default intent mapping:
|
|
|
36
36
|
|
|
37
37
|
If the proposal is not approved yet, stop immediately.
|
|
38
38
|
|
|
39
|
+
### 1.1 User Confirmation Request Rules
|
|
40
|
+
|
|
41
|
+
When execution requires the user to confirm the implementation path, workspace policy, continued implementation, return to design revision, or post-completion closeout action, render "user choice required" as a standalone block titled `User Confirmation Request`. Do not mix conclusions, verification results, recommendations, and pending confirmation into one paragraph.
|
|
42
|
+
|
|
43
|
+
The confirmation block must include:
|
|
44
|
+
|
|
45
|
+
- one explicit instruction: `Reply with a number.`
|
|
46
|
+
- 2-6 numbered options, with item 1 usually marked as `Recommended`
|
|
47
|
+
- `Other:` explaining how non-numbered content will be handled, usually as continued implementation work or extra constraints
|
|
48
|
+
- if the user adds constraints but still has not made a clear choice, continue presenting updated numbered options until the user chooses, stops, or explicitly tells you to continue
|
|
49
|
+
|
|
50
|
+
If the platform provides structured question UI such as `ask user questions`, `request_user_input`, or an equivalent mechanism, prefer that for these numbered options. If no such mechanism is available, render the `User Confirmation Request` block in the normal message. In either form, do not end with only a sentence like "the next step is that phase" or "I recommend this path."
|
|
51
|
+
|
|
39
52
|
If the proposal phase already confirmed the implementation path:
|
|
40
53
|
|
|
41
54
|
- user chose `Superpowers`: continue into Superpowers Make Plan.
|
|
@@ -214,7 +227,15 @@ After running those commands, the user-facing report must include all of the fol
|
|
|
214
227
|
|
|
215
228
|
### 5.3 Numbered Next-Step Menu Template
|
|
216
229
|
|
|
217
|
-
|
|
230
|
+
Before generating the next-step menu, inspect the current closeout state with the script. Do not infer whether merge/worktree deletion is needed from branch names, path names, or intuition:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
"$ONESPEC_BASH" "$ONESPEC_CLOSEOUT" recommend-actions <change-id>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Generate the menu from the inspected state:
|
|
237
|
+
|
|
238
|
+
- If `temporary_worktree: true`, the current implementation lives in a temporary worktree. The report must end with a menu equivalent to:
|
|
218
239
|
|
|
219
240
|
```text
|
|
220
241
|
---
|
|
@@ -231,7 +252,7 @@ Other: any non-numbered content means continue modifying the current implementat
|
|
|
231
252
|
---
|
|
232
253
|
```
|
|
233
254
|
|
|
234
|
-
If the current
|
|
255
|
+
- If `temporary_worktree: false`, the current implementation is already on the target branch/workspace and there is no temporary worktree to merge back or delete. Regardless of whether that branch is `main`, `master`, `develop`, `feature/*`, or any other name, do not show "merge the branch into the base branch" or "delete the current temporary worktree". In that case the closeout menu must collapse to a single archive-only option:
|
|
235
256
|
|
|
236
257
|
```text
|
|
237
258
|
---
|
|
@@ -241,18 +262,19 @@ Current branch: <branch>
|
|
|
241
262
|
Current workspace: <path>
|
|
242
263
|
Origin: <origin_branch> @ <origin_workspace_path>
|
|
243
264
|
|
|
244
|
-
1. Archive only
|
|
265
|
+
1. Archive only (current checkout is not a temporary worktree; no branch merge or worktree deletion is needed)
|
|
245
266
|
Other: any non-numbered content means continue modifying the current implementation; if the user gives no input, remain paused in the current review stage
|
|
246
267
|
---
|
|
247
268
|
```
|
|
248
269
|
|
|
249
|
-
In other words,
|
|
270
|
+
In other words, when `temporary_worktree: false`, do not prompt for branch merge or worktree deletion on any target branch.
|
|
250
271
|
|
|
251
|
-
If the current branch or workspace differs from `origin_*`, add an explicit note that implementation currently lives in a temporary branch or temporary worktree and that any non-numbered reply will be treated as a request for more implementation work.
|
|
272
|
+
If the script reports that the current branch or workspace differs from `origin_*`, add an explicit note that implementation currently lives in a temporary branch or temporary worktree and that any non-numbered reply will be treated as a request for more implementation work.
|
|
252
273
|
|
|
253
|
-
- If the user chooses `1`, archive phase must archive first, then merge the branch into the base branch.
|
|
254
|
-
- If the user chooses `2`, archive phase must archive only, without merging and without auto-deleting the current worktree.
|
|
255
|
-
- If the user chooses `3`, archive phase must delete the temporary worktree and discard the code without archiving.
|
|
274
|
+
- If `temporary_worktree: true` and the user chooses `1`, archive phase must archive first, then merge the branch into the base branch, then delete the temporary worktree.
|
|
275
|
+
- If `temporary_worktree: true` and the user chooses `2`, archive phase must archive only, without merging and without auto-deleting the current worktree.
|
|
276
|
+
- If `temporary_worktree: true` and the user chooses `3`, archive phase must delete the temporary worktree and discard the code without archiving.
|
|
277
|
+
- If `temporary_worktree: false` and the user chooses `1`, archive phase must archive only; it must not merge a branch or delete any workspace/worktree.
|
|
256
278
|
|
|
257
279
|
Do not stop at an abstract note such as "the next step is archive phase" or just "do review-closeout". You must also give the user a concrete numbered menu.
|
|
258
280
|
|
|
@@ -24,7 +24,7 @@ Use rules:
|
|
|
24
24
|
|
|
25
25
|
- Use only when the user explicitly asks for `onespec-fast`, the fast path, fast apply, automatic OpenSpec proposal/implementation/archive, or automatic end-to-end execution.
|
|
26
26
|
- Do not ask the user to name the change. Generate a short kebab-case `change-id`; append a numeric suffix if needed.
|
|
27
|
-
- Read the minimum needed context: `openspec/config.yaml`,
|
|
27
|
+
- Read the minimum needed context: `openspec/config.yaml`, relevant `openspec/specs/**`, project entry docs, current branch, and workspace state.
|
|
28
28
|
- Pause only when required OpenSpec context is too incomplete to produce a valid proposal, or project docs explicitly forbid automatic edits on the current branch.
|
|
29
29
|
|
|
30
30
|
## 2. Direct Proposal
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kafka0102/onespec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "OpenSpec + Superpowers workflow skill installer for mainstream SKILL.md agents",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,5 +38,8 @@
|
|
|
38
38
|
"engines": {
|
|
39
39
|
"node": ">=20"
|
|
40
40
|
},
|
|
41
|
-
"license": "MIT"
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@inquirer/prompts": "^8.4.3"
|
|
44
|
+
}
|
|
42
45
|
}
|
package/src/cli.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import readline from 'node:readline/promises';
|
|
3
|
-
import { stdin as input, stdout as output } from 'node:process';
|
|
4
2
|
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { checkbox, select, confirm } from '@inquirer/prompts';
|
|
5
4
|
|
|
6
5
|
import { doctorProject } from './doctor.js';
|
|
7
6
|
import { SUPPORTED_LANGUAGES } from './init.js';
|
|
8
|
-
import { getPlatform } from './platforms.js';
|
|
7
|
+
import { getPlatform, PLATFORMS } from './platforms.js';
|
|
9
8
|
import {
|
|
10
9
|
detectExistingOneSpecPlatforms,
|
|
11
10
|
detectPlatforms,
|
|
@@ -62,8 +61,57 @@ function parseArgs(argv) {
|
|
|
62
61
|
return { command, options };
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
function
|
|
66
|
-
|
|
64
|
+
async function selectScope(options) {
|
|
65
|
+
if (options.scope) return options.scope;
|
|
66
|
+
if (options.yes) return 'project';
|
|
67
|
+
|
|
68
|
+
return select({
|
|
69
|
+
message: 'Install scope:',
|
|
70
|
+
choices: [
|
|
71
|
+
{ name: 'Project (current directory)', value: 'project' },
|
|
72
|
+
{ name: 'Global (home directory)', value: 'global' },
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function selectLanguage(options) {
|
|
78
|
+
if (options.yes) return 'zh';
|
|
79
|
+
|
|
80
|
+
const langId = await select({
|
|
81
|
+
message: 'Language for OneSpec skills:',
|
|
82
|
+
choices: Object.entries(SUPPORTED_LANGUAGES).map(([id, lang]) => ({ name: lang.name, value: id })),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return langId;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function selectPlatforms(detected, options) {
|
|
89
|
+
const choices = SUPPORTED_PLATFORM_IDS.map((platformId) => {
|
|
90
|
+
const platform = getPlatform(platformId);
|
|
91
|
+
return {
|
|
92
|
+
name: `${platform.name}${detected.has(platformId) ? ' (detected)' : ''}`,
|
|
93
|
+
value: platformId,
|
|
94
|
+
checked: detected.has(platformId),
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (options.yes) {
|
|
99
|
+
const selected = [...detected];
|
|
100
|
+
return selected.length > 0 ? selected : ['codex'];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return checkbox({ message: 'Select platforms to set up:', choices, required: true });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function askOverwrite(existingPlatforms, options) {
|
|
107
|
+
if (options.overwrite || existingPlatforms.length === 0) {
|
|
108
|
+
return options.overwrite;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return confirm({
|
|
112
|
+
message: `OneSpec skills already exist for ${existingPlatforms.join(', ')}. Overwrite existing items?`,
|
|
113
|
+
default: false,
|
|
114
|
+
});
|
|
67
115
|
}
|
|
68
116
|
|
|
69
117
|
async function askInitOptions(options) {
|
|
@@ -80,79 +128,24 @@ async function askInitOptions(options) {
|
|
|
80
128
|
};
|
|
81
129
|
}
|
|
82
130
|
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const selectedPlatforms = resolvePlatformSelection(platformAnswer, defaultPlatforms);
|
|
102
|
-
const scopeAnswer =
|
|
103
|
-
options.scope ??
|
|
104
|
-
(await rl.question('安装范围?输入 project 或 global(默认 project):'));
|
|
105
|
-
const resolvedScope = scopeAnswer.trim() || 'project';
|
|
106
|
-
const languageAnswer =
|
|
107
|
-
options.language ??
|
|
108
|
-
(await rl.question('Skill 语言?输入 zh 或 en(默认 zh):'));
|
|
109
|
-
const existingPlatforms = await detectExistingOneSpecPlatforms(
|
|
110
|
-
options.targetPath,
|
|
111
|
-
resolvedScope,
|
|
112
|
-
selectedPlatforms,
|
|
113
|
-
);
|
|
114
|
-
const overwriteAnswer =
|
|
115
|
-
options.overwrite || existingPlatforms.length === 0
|
|
116
|
-
? 'no'
|
|
117
|
-
: await rl.question(
|
|
118
|
-
`检测到这些平台已存在 OneSpec skill:${existingPlatforms.join(', ')}。是否覆盖已存在项?输入 yes 或 no(默认 no):`,
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
...options,
|
|
123
|
-
platforms: selectedPlatforms,
|
|
124
|
-
scope: resolvedScope,
|
|
125
|
-
language: languageAnswer.trim() || 'zh',
|
|
126
|
-
overwrite: options.overwrite || normalizeYesNo(overwriteAnswer),
|
|
127
|
-
};
|
|
128
|
-
} finally {
|
|
129
|
-
rl.close();
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function resolvePlatformSelection(answer, defaultPlatforms) {
|
|
134
|
-
const trimmed = answer.trim();
|
|
135
|
-
if (!trimmed) {
|
|
136
|
-
return defaultPlatforms;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const numbered = trimmed
|
|
140
|
-
.split(',')
|
|
141
|
-
.map((value) => value.trim())
|
|
142
|
-
.filter(Boolean)
|
|
143
|
-
.map((value) => {
|
|
144
|
-
if (!/^\d+$/.test(value)) {
|
|
145
|
-
return value;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const index = Number.parseInt(value, 10) - 1;
|
|
149
|
-
if (index < 0 || index >= SUPPORTED_PLATFORM_IDS.length) {
|
|
150
|
-
throw new Error(`Unsupported platform selection: ${value}`);
|
|
151
|
-
}
|
|
152
|
-
return SUPPORTED_PLATFORM_IDS[index];
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
return parsePlatformList(numbered);
|
|
131
|
+
const detectedSet = new Set(detectedPlatforms);
|
|
132
|
+
const selectedPlatforms = explicitPlatforms.length > 0 ? explicitPlatforms : await selectPlatforms(detectedSet, options);
|
|
133
|
+
const resolvedScope = await selectScope(options);
|
|
134
|
+
const language = await selectLanguage(options);
|
|
135
|
+
const existingPlatforms = await detectExistingOneSpecPlatforms(
|
|
136
|
+
options.targetPath,
|
|
137
|
+
resolvedScope,
|
|
138
|
+
selectedPlatforms,
|
|
139
|
+
);
|
|
140
|
+
const overwrite = await askOverwrite(existingPlatforms, options);
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
...options,
|
|
144
|
+
platforms: selectedPlatforms,
|
|
145
|
+
scope: resolvedScope,
|
|
146
|
+
language,
|
|
147
|
+
overwrite,
|
|
148
|
+
};
|
|
156
149
|
}
|
|
157
150
|
|
|
158
151
|
function printHelp() {
|
package/src/platforms.js
CHANGED
|
@@ -21,7 +21,7 @@ export const PLATFORMS = {
|
|
|
21
21
|
projectSkillsDir: path.join('.claude', 'skills'),
|
|
22
22
|
globalSkillsDir: path.join(claudeHome, 'skills'),
|
|
23
23
|
discoveryRoots: [],
|
|
24
|
-
openspecToolId: 'claude
|
|
24
|
+
openspecToolId: 'claude',
|
|
25
25
|
},
|
|
26
26
|
cursor: {
|
|
27
27
|
id: 'cursor',
|
|
@@ -37,7 +37,7 @@ export const PLATFORMS = {
|
|
|
37
37
|
projectSkillsDir: path.join('.agents', 'skills'),
|
|
38
38
|
globalSkillsDir: path.join(home, '.gemini', 'skills'),
|
|
39
39
|
discoveryRoots: [path.join(home, '.agents', 'skills')],
|
|
40
|
-
openspecToolId: 'gemini
|
|
40
|
+
openspecToolId: 'gemini',
|
|
41
41
|
},
|
|
42
42
|
'github-copilot': {
|
|
43
43
|
id: 'github-copilot',
|