@flyin-ai/alloy 0.2.0-beta.1 → 0.2.0-beta.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/commands/alloy/apply.md +222 -430
- package/commands/alloy/archive.md +156 -132
- package/commands/alloy/discard.md +26 -11
- package/commands/alloy/finish.md +212 -116
- package/commands/alloy/fix.md +102 -247
- package/commands/alloy/plan.md +204 -301
- package/commands/alloy/references/apply-precheck.md +21 -0
- package/commands/alloy/references/apply-rationalizations.md +18 -0
- package/commands/alloy/references/apply-subagent-commit.md +49 -0
- package/commands/alloy/references/apply-worktree.md +130 -0
- package/commands/alloy/references/archive-rationalizations.md +16 -0
- package/commands/alloy/references/archive-worktree-cleanup.md +94 -0
- package/commands/alloy/references/artifact-hash-commit.md +49 -0
- package/commands/alloy/references/branch-naming.md +65 -0
- package/commands/alloy/references/branch-validation.md +36 -0
- package/commands/alloy/references/fix-precommit-check.md +58 -0
- package/commands/alloy/references/interaction-style.md +34 -1
- package/commands/alloy/references/main-branch-detection.md +3 -6
- package/commands/alloy/references/phase-downgrade-path.md +27 -0
- package/commands/alloy/references/plan-rollback.md +84 -0
- package/commands/alloy/references/spec-sync.md +62 -0
- package/commands/alloy/references/start-rationalizations.md +18 -0
- package/commands/alloy/start.md +178 -238
- package/dist/cli/commands/completion.js +13 -2
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/internal/artifact.d.ts +7 -0
- package/dist/cli/commands/internal/artifact.js +70 -0
- package/dist/cli/commands/internal/artifact.js.map +1 -0
- package/dist/cli/commands/internal/guard.js +204 -2
- package/dist/cli/commands/internal/guard.js.map +1 -1
- package/dist/cli/commands/internal/progress.d.ts +10 -0
- package/dist/cli/commands/internal/progress.js +70 -0
- package/dist/cli/commands/internal/progress.js.map +1 -0
- package/dist/cli/commands/internal/spec-audit.d.ts +42 -0
- package/dist/cli/commands/internal/spec-audit.js +363 -0
- package/dist/cli/commands/internal/spec-audit.js.map +1 -0
- package/dist/cli/commands/internal/state.js +4 -0
- package/dist/cli/commands/internal/state.js.map +1 -1
- package/dist/cli/index.js +30 -0
- package/dist/cli/index.js.map +1 -1
- package/package.json +2 -1
package/commands/alloy/start.md
CHANGED
|
@@ -3,35 +3,74 @@ name: "Alloy: Start"
|
|
|
3
3
|
description: 新功能构思或接续已有工作时调用
|
|
4
4
|
category: Workflow
|
|
5
5
|
tags: [alloy, workflow]
|
|
6
|
+
spec: 01-product-spec/01-start-spec.md
|
|
7
|
+
behaviors:
|
|
8
|
+
preconditions: 5
|
|
9
|
+
hard_stops: 8
|
|
10
|
+
user_gates: 8
|
|
11
|
+
warns: 2
|
|
12
|
+
artifacts: [draft]
|
|
13
|
+
transitions_to: started
|
|
14
|
+
external_calls: [opsx:explore, opsx:new, superpowers:brainstorming]
|
|
6
15
|
---
|
|
7
16
|
|
|
8
17
|
# alloy-start
|
|
9
18
|
|
|
10
|
-
你是 Alloy
|
|
19
|
+
你是 Alloy 工作流的智能入口。检测状态、路由到正确流程、调度外部技能完成探查和需求设计,产出 draft.md。
|
|
11
20
|
|
|
12
|
-
**核心原则:把实际工作委托给专门的技能,不要自己做。Alloy 是编排器,不是执行者。**
|
|
21
|
+
**核心原则:把实际工作委托给专门的技能,不要自己做。Alloy 是编排器,不是执行者。** draft.md 以 hash-lock + commit 入 records,禁直接编辑。
|
|
13
22
|
|
|
14
|
-
|
|
23
|
+
```
|
|
24
|
+
[HARD_STOP] NO WORK ON MAIN BRANCH + NO AUTO ADVANCE
|
|
25
|
+
每个 change 必须在独立 feature 分支上;start 完成后绝不自动进 plan
|
|
26
|
+
违反字面 = 违反精神:哪怕"用户在催赶时间在 main 上先建文件"或"用户上次也是接 plan 这次猜跳过 USER_GATE",也算违反 Iron Law
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> **`<TIMESTAMP>`:** 每次渲染阶段头部时执行 `date "+%Y-%m-%d %H:%M:%S"` 获取本地时间。`<START_TIME>` 是"全新开始"路径中捕获的时间——agent 捕获后复用于 header 和 phase_timings。`<created_at>` 从 `.alloy.yaml` 读取。
|
|
30
|
+
|
|
31
|
+
**交互规则:** `🔴 STOP` 等价 `USER_GATE`,必须用 `AskUserQuestion`(`commands/alloy/references/interaction-style.md`,含"沉默 ≠ 授权"通用禁令)。跳过任何 USER_GATE / 批量打包 / 基于内容跳过 = 违反 Iron Law。
|
|
32
|
+
|
|
33
|
+
**状态符号:** `⛔` = HARD_STOP / PRECONDITION_FAIL,`🔴` = USER_GATE,`⚠️` = WARN(视觉规范 §七)。
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### Red Flags(第三层防御——任一借口出现即 STOP)
|
|
38
|
+
|
|
39
|
+
主文件保留 5 条核心借口,完整 12 条见 `commands/alloy/references/start-rationalizations.md`。
|
|
40
|
+
|
|
41
|
+
| 借口 | 现实 |
|
|
42
|
+
|------|------|
|
|
43
|
+
| "不用建分支了,就在 main 上干吧" | ⛔ HARD_STOP:主分支污染不可逆。建分支只需 2 秒。违反字面 = 违反精神:哪怕"只是先建个目录后面再切"也算(Iron Law 第一层)。 |
|
|
44
|
+
| "不用 brainstorming,直接写代码" | brainstorming 不可跳过。跳过需求设计 = 规格和代码分叉的起点。 |
|
|
45
|
+
| "start 完成了,直接进 plan" / "用户没回复,我先继续" | ⛔ HARD_STOP:start 完成后绝不自动进入 plan。沉默 ≠ 授权(Iron Law 第二层)。替用户做阶段转换 = 剥夺审查机会。 |
|
|
46
|
+
| "openspec/changes/<name>/ 已经有了,直接复用" | ⛔ PRECONDITION_FAIL:目录已存在 = #12 冲突。USER_GATE 让用户决策(改名 / 接续 / 中止),禁 agent 自动复用——可能覆盖用户既有工作。 |
|
|
47
|
+
| "git init 后 reset --hard 一下,把环境清干净" | ⛔ HARD_STOP:git 初始化失败禁 reset --hard / clean -fd / checkout .(§3.5.1 git 自救禁令)。退出 skill 让用户处理。 |
|
|
15
48
|
|
|
16
49
|
---
|
|
17
50
|
|
|
18
|
-
##
|
|
51
|
+
## 状态检测(前置门)
|
|
52
|
+
|
|
53
|
+
**第一步**(⛔ PRECONDITION_FAIL):检查 `openspec/config.yaml` 是否存在——不存在则提示用户 `alloy init`,agent 不得自动初始化(init 会写 `.claude/` / 模板等关键文件,必须由用户主动触发)。
|
|
19
54
|
|
|
20
|
-
|
|
55
|
+
**第二步:** 扫描 `openspec/changes/*/.alloy.yaml`,统计 phase != `finished` 的 change,作为路由依据:
|
|
56
|
+
- 0 个活跃 change + 提供 topic → 全新开始
|
|
57
|
+
- 0 个活跃 change + 无 topic → 自由探索
|
|
58
|
+
- 1 个活跃 change → 接续
|
|
59
|
+
- 多个活跃 change → 多选
|
|
21
60
|
|
|
22
|
-
|
|
61
|
+
**第三步**(⛔ PRECONDITION_FAIL):「全新开始」与「强制新建」路径强制 Skill 预检——cmd: opsx/explore opsx/new, skill: brainstorming。读取 `commands/alloy/references/skill-precheck.md` 检测,任一不可用 → 引导 `alloy init`,不存在降级。
|
|
23
62
|
|
|
24
|
-
|
|
63
|
+
**第四步**(⛔ PRECONDITION_FAIL):「全新开始」与「强制新建」路径强制 git 仓库就绪——`git rev-parse --git-dir` 失败时尝试 `git init` 兜底(详见全新开始步骤 2);兜底失败 → 退出 skill。
|
|
25
64
|
|
|
26
65
|
---
|
|
27
66
|
|
|
28
67
|
## 全新开始(无活跃 change + 用户提供了 topic)
|
|
29
68
|
|
|
30
|
-
|
|
69
|
+
**捕获阶段启动时间:**
|
|
31
70
|
```bash
|
|
32
71
|
date "+%Y-%m-%d %H:%M:%S"
|
|
33
72
|
```
|
|
34
|
-
>
|
|
73
|
+
> 不要混用 bash 变量——bash 状态在两次工具调用间不持久。直接捕获 date 输出文本。
|
|
35
74
|
|
|
36
75
|
```
|
|
37
76
|
┌──────────────────────────────────────┐
|
|
@@ -40,63 +79,38 @@ date "+%Y-%m-%d %H:%M:%S"
|
|
|
40
79
|
└──────────────────────────────────────┘
|
|
41
80
|
```
|
|
42
81
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
**Skill 预检:** 确认以下依赖可用:
|
|
46
|
-
cmd: opsx/explore opsx/new
|
|
47
|
-
skill: brainstorming
|
|
82
|
+
> **前置门:** Skill 预检 + git 仓库就绪已在「状态检测」第三/四步完成(⛔ PRECONDITION_FAIL)。本路径假设两者已通过。
|
|
48
83
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
> 正在探查项目上下文和需求空间...
|
|
52
|
-
|
|
53
|
-
**立即执行:** 使用 Skill 工具加载 `opsx:explore` 技能。禁止跳过此步骤。
|
|
54
|
-
|
|
55
|
-
技能加载后,按其指引自由探索项目上下文和需求空间。
|
|
56
|
-
|
|
57
|
-
**交互风格:** 探查结果反馈给用户时,使用 `AskUserQuestion` 工具呈现结构化选项。详见 `commands/alloy/references/interaction-style.md`。箭头上下选择、Enter 确认——不要用纯文本 "(a)(b)(c)" 让用户打字。
|
|
84
|
+
### [Step 1/2] 上下文探查
|
|
58
85
|
|
|
59
|
-
|
|
86
|
+
加载 `opsx:explore` 技能,按其指引探索项目上下文。
|
|
60
87
|
|
|
61
|
-
|
|
62
|
-
- **§6 值得推广**:有哪些未勾选的 carry-forward item?这次可以直接勾上
|
|
63
|
-
- **§4 技能跳过模式**:如果连续两个 retrospective 中同一技能被 ✗,提醒用户该技能可能不适合本项目
|
|
88
|
+
**交互风格:** 使用 `AskUserQuestion` 工具。详见 `commands/alloy/references/interaction-style.md`。
|
|
64
89
|
|
|
65
|
-
|
|
90
|
+
**额外上下文:** 扫描 `openspec/changes/archive/` 下最近 3 个 `retrospective.md`,提取 §5 意外发现、§6 值得推广、§4 技能跳过模式,作为本次 brainstorming 参考。
|
|
66
91
|
|
|
67
92
|
---
|
|
68
93
|
|
|
69
94
|
### [Step 2/2] 需求设计
|
|
70
95
|
|
|
71
|
-
|
|
96
|
+
加载 `superpowers:brainstorming` 技能,传入探查结果和主题:
|
|
72
97
|
|
|
73
|
-
**立即执行:** 使用 Skill 工具加载 `superpowers:brainstorming` 技能。禁止跳过此步骤。
|
|
74
|
-
|
|
75
|
-
将探查结果作为 ARGUMENTS 传入:
|
|
76
98
|
```
|
|
77
|
-
探查结果:<Step 1
|
|
99
|
+
探查结果:<Step 1 关键发现摘要>
|
|
78
100
|
主题:<topic>
|
|
79
101
|
项目类型:<新项目/存量项目>
|
|
80
102
|
|
|
81
|
-
**Alloy 流程覆盖:** 本调用在 Alloy start 流程内,brainstorming 完成后产出是 draft.md
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
brainstorming 每个问题都是沟通成本。使用平台的交互式提示工具(Claude Code 中为 `AskUserQuestion`)来降低来回次数。**不要用纯文本 "(a)(b)(c)"——那只是换了格式的开放式提问。**
|
|
103
|
+
**Alloy 流程覆盖:** 本调用在 Alloy start 流程内,brainstorming 完成后产出是 draft.md
|
|
104
|
+
(openspec/changes/<name>/draft.md),不是 docs/superpowers/specs/ 文件。
|
|
105
|
+
请跳过 brainstorming checklist 中的"Write design doc"和"Invoke writing-plans"步骤。
|
|
86
106
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- **关键决策单选、范围确认多选:** 架构选择用 radio(互斥),功能范围用 checkbox(独立),不混用。
|
|
92
|
-
- **给出默认推荐:** 推荐的选项在 `description` 中标注理由,让用户可以一键确认而不是逐项评估。
|
|
107
|
+
**交互风格:** 使用 AskUserQuestion 组件,不用纯文本 (a)(b)(c)。
|
|
108
|
+
单选用 radio,多选用 checkbox,代码方案对比用 preview。
|
|
109
|
+
每次提问不超过 4 个问题,相关问题合并到一次调用。
|
|
110
|
+
给出默认推荐——推荐选项在 description 中标注理由。
|
|
93
111
|
```
|
|
94
112
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
**brainstorming 负责"想清楚要做什么"——通过交互式问答明确问题、方案和关键决策。** 用户确认方案后,这一步的产出是 `draft.md`,不是 superpowers spec 文件。
|
|
98
|
-
|
|
99
|
-
用户确认方案后,生成 `draft.md`:
|
|
113
|
+
**用户确认方案后,生成 draft.md**(不是 spec 文件)。用户要求调整时回到 brainstorming 继续。
|
|
100
114
|
|
|
101
115
|
```markdown
|
|
102
116
|
# [功能名称]
|
|
@@ -108,188 +122,144 @@ brainstorming 每个问题都是沟通成本。使用平台的交互式提示工
|
|
|
108
122
|
<!-- 方案概述 -->
|
|
109
123
|
|
|
110
124
|
## 关键决策
|
|
111
|
-
<!-- brainstorming
|
|
125
|
+
<!-- brainstorming 中确定的关键技术决策及理由 -->
|
|
112
126
|
|
|
113
127
|
## 范围与边界
|
|
114
128
|
<!-- 做什么、明确不做什么 -->
|
|
115
129
|
```
|
|
116
130
|
|
|
117
|
-
**用户明确确认方案之前,不要生成 draft.md。**
|
|
131
|
+
> [HARD_STOP] **用户明确确认方案之前,不要生成 draft.md。**
|
|
132
|
+
> 违反字面 = 违反精神:哪怕"内容已经基本明确再补审查",也算违反——审查窗口是 USER_GATE,不可后置。
|
|
118
133
|
|
|
119
|
-
|
|
120
|
-
- brainstorming 完成后生成了 `docs/superpowers/specs/` 文件——draft.md 是 brainstorming 在 alloy 流程中的唯一产出
|
|
121
|
-
- brainstorming 完成后 invoke writing-plans——那是独立使用 brainstorming 时的行为,在 alloy:start 中下一步是生成 draft.md
|
|
122
|
-
- 用户说"还行"、"可以"就直接生成——追问他是否满意关键决策和范围边界
|
|
134
|
+
---
|
|
123
135
|
|
|
124
|
-
|
|
136
|
+
用户确认方案后,执行以下步骤:
|
|
125
137
|
|
|
126
|
-
|
|
138
|
+
> **交互风格恢复(HARD_STOP):** brainstorming 已结束。从此刻起,所有 `🔴 USER_GATE` 必须恢复使用 `AskUserQuestion` 工具(`commands/alloy/references/interaction-style.md`),不用纯文本 (a)(b)(c)。Agent 刚从 brainstorming 的"每次一个问题"模式出来,容易延续纯文本习惯——这是 Iron Law 违规。违反字面 = 违反精神:哪怕"就这一个确认用文本也行",也算违反——USER_GATE 必须 AskUserQuestion。
|
|
127
139
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
| "已经在某个分支上了,跳过分支步骤" | 在某个分支上 ≠ 在正确的分支上。仍需验证当前分支 ≠ 主分支,并让用户确认。 |
|
|
132
|
-
| "分支创建是可选步骤" | 分支创建不是可选的——它是步骤 3 的硬性闸门。没有通过 ⑥ 验证,步骤 4-9 全部禁止执行。 |
|
|
133
|
-
| "用户没提分支,继续吧" | 用户没提 ≠ 用户同意跳过。闸门不需要用户主动请求才生效——它默认生效,除非用户明确选择分支。 |
|
|
134
|
-
| "项目简单/一个人开发,不需要分支" | 分支隔离保护的是 discard 安全性,不是团队协作。简单项目一样需要独立分支,否则 discard 会丢失主分支上的无关变更。 |
|
|
135
|
-
| "不用 brainstorming 了,直接写代码" | brainstorming 不是可选项。跳过需求设计 = 规格和代码分叉的起点。必须加载 superpowers:brainstorming。 |
|
|
136
|
-
| "我一个人开发,不用那么正式" | 流程保护的是一致性和可追溯性,不是团队规模。一个人的项目和团队项目的闸门完全一样。 |
|
|
137
|
-
| "我看过了,内容都对"(跳过审查) | 用户"看过了"不等于审查到位。必须按流程确认 change name、主分支、feature 分支。 |
|
|
138
|
-
| "brainstorming 完成了,写 spec 文件吧" | Alloy start 的产出是 draft.md,不是 docs/superpowers/specs/ 文件。brainstorming 完成后直接输出方案,由 Alloy 流程负责生成 draft.md。 |
|
|
139
|
-
| "start 完成了,我帮你直接进 plan" | start 完成后绝不自动进入 plan。即使用户之前说过"赶紧做完",也需要用户在看过 draft.md 后明确运行 /alloy:plan。替用户做阶段转换决定 = 剥夺审查机会。 |
|
|
140
|
-
| "用户没回复,我先继续生成 proposal 吧" | 用户沉默 ≠ 授权继续。在审查窗口等待用户明确选 (a) 或 (b)。擅自继续 = 生成的制品未经审查,后期返工代价远大于等待时间。 |
|
|
141
|
-
| "draft.md 在 brainstorming 时已经讨论过了,直接 commit 吧" | brainstorming 讨论的是方案概念,draft.md 是最终文本。两者不等价——文本可能有措辞偏差、遗漏细节。必须展示 draft.md 完整内容,等用户确认后才能 commit。 |
|
|
140
|
+
> **git 自救禁令(§3.5.1 内嵌约束,HARD_STOP):** 步骤 2 git init / 步骤 3 分支创建/切换 / 步骤 9 commit 任何环节失败,禁 agent 运行 `git reset --hard` / `git checkout .` / `git restore .` / `git stash` / `git clean -fd` / `git push --force` —— 退出 skill 让用户处理是唯一合法路径。
|
|
141
|
+
>
|
|
142
|
+
> **git add 限路径(§5.2.1 内嵌约束,HARD_STOP):** 所有 commit 用精确路径(`.claude/` `openspec/` `CLAUDE.md` 等明确列举),禁 `-A`/`-a`/`.`。违反字面 = 违反精神:哪怕"反正只改了已知文件",也禁通配——可能把 `.superpowers/` 临时目录或测试残留一并 commit。
|
|
142
143
|
|
|
143
|
-
|
|
144
|
+
1. **建议 change name**——kebab-case,🔴 USER_GATE: 确认 change name(建议名 / 自定义)。
|
|
144
145
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
1. **建议 change name**——根据确认的方案建议 kebab-case 名称,用户确认
|
|
146
|
+
> [HARD_STOP] **未确认时禁止继续步骤 2-9。**
|
|
147
|
+
> 违反字面 = 违反精神:哪怕"name 大概就这个先建分支",也算违反——name 是 directory + branch + records 主键。
|
|
148
148
|
|
|
149
149
|
2. **确保 git 仓库就绪:**
|
|
150
|
-
|
|
151
150
|
```bash
|
|
152
151
|
if ! git rev-parse --git-dir 2>/dev/null; then
|
|
153
152
|
git init
|
|
154
|
-
# 空项目:先提交基础设施作为锚点,确保 HEAD 存在以便后续创建分支
|
|
155
153
|
git add .claude/ .gitignore openspec/config.yaml openspec/schemas/ 2>/dev/null
|
|
156
154
|
[ -f CLAUDE.md ] && git add CLAUDE.md 2>/dev/null
|
|
157
155
|
git commit -m "chore: alloy init 项目初始化"
|
|
158
156
|
fi
|
|
159
157
|
```
|
|
160
158
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
3. **分支选择**——在创建 change 目录之前完成分支切换,确保所有制品落在 feature 分支上:
|
|
164
|
-
|
|
165
|
-
**① 自动识别主分支:** 读取 `commands/alloy/references/main-branch-detection.md`,按 3 级优先级检测主分支。
|
|
159
|
+
3. **分支选择**——创建 change 目录之前完成,确保所有制品落在 feature 分支上:
|
|
166
160
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
161
|
+
**① 主分支检测:** 读取 `commands/alloy/references/main-branch-detection.md`。若 config 已有 `main_branch`,直接用。否则检测后 🔴 USER_GATE: 确认主分支(检测值 / 自定义)。确认后写入并提交(§5.2.1 git add 限路径):
|
|
162
|
+
```bash
|
|
163
|
+
alloy _config write . main_branch <确认值>
|
|
164
|
+
git add openspec/config.yaml
|
|
165
|
+
git diff --cached --quiet || git commit -m "chore: 配置主分支"
|
|
166
|
+
```
|
|
173
167
|
|
|
174
|
-
|
|
168
|
+
**② 当前分支决策**(🔴 USER_GATE,3 种情况共用同款语义节点):
|
|
175
169
|
```bash
|
|
176
170
|
CURRENT_BRANCH=$(git branch --show-current)
|
|
177
|
-
CHANGENAME="<name>"
|
|
178
171
|
```
|
|
179
172
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
-
|
|
183
|
-
- **在 feature 分支上且名称包含 change 名**(如 `feature/<name>` 或 `fix/<name>`)→ 提示"当前已在 `<$CURRENT_BRANCH>`,直接在该分支上继续工作?[Y/n]"
|
|
184
|
-
- 选 Y → 使用当前分支,继续步骤 4
|
|
185
|
-
- 选 n → 展示选项(见⑤)
|
|
186
|
-
- **在非主分支的已有分支上** → 展示选项(见⑤)
|
|
173
|
+
- **在主分支上** → ⛔ HARD_STOP:"不允许在主分支开发。" → 🔴 USER_GATE: 只展示"新建分支"
|
|
174
|
+
- **在 feature 分支且名称含 change 名** → 🔴 USER_GATE: 继续使用当前分支 / 新建分支
|
|
175
|
+
- **在非主分支的已有分支上** → 🔴 USER_GATE: 切换到已有分支 / 新建分支
|
|
187
176
|
|
|
188
|
-
|
|
177
|
+
无可用本地非主分支时 → 直接新建。
|
|
189
178
|
|
|
190
|
-
|
|
191
|
-
> 选择工作分支
|
|
192
|
-
> ──────────────────────────────────────
|
|
193
|
-
>
|
|
194
|
-
> 当前在 `<$CURRENT_BRANCH>`,主分支:`<main_branch>`
|
|
195
|
-
>
|
|
196
|
-
> 1. 切换到已有分支 —— 选择非主分支的已有分支
|
|
197
|
-
> 2. 新建分支 —— 创建新 feature 分支并切换
|
|
179
|
+
新建分支命名:默认 `feature/<change-name>`,用户可自定义。
|
|
198
180
|
|
|
199
|
-
|
|
181
|
+
**⛔ PRECONDITION_FAIL 白名单校验**(读取 `commands/alloy/references/branch-naming.md`):自定义分支名必须以 `feature/` `fix/` `docs/` `refactor/` `test/` `chore/` 之一开头,后缀 kebab-case,且不与主分支同名。校验失败 → USER_GATE 让用户重新输入合法名称,**禁 agent 自动改写后继续**。
|
|
200
182
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
- **选 1:** 列出本地非主分支(`git branch` 排除主分支),用户选择后执行 `git checkout <branch>`
|
|
204
|
-
- **选 2:** 新建分支命名:
|
|
205
|
-
- 默认建议:`feature/<change-name>`
|
|
206
|
-
- 用户可输入自定义名称
|
|
207
|
-
- 校验:不允许与主分支同名
|
|
208
|
-
- `git checkout -b <branch-name>`
|
|
209
|
-
|
|
210
|
-
**⑥ 分支验证——HARD STOP:** 分支创建/切换后,必须验证才能继续。这是防止在主分支上开发的关键闸门——没有这个检查,步骤 3 的所有逻辑都是空谈。
|
|
183
|
+
通过校验后:`git checkout -b <branch-name>`
|
|
211
184
|
|
|
185
|
+
**③ 分支验证(⛔ HARD_STOP):** 创建/切换后必须验证才能继续:
|
|
212
186
|
```bash
|
|
213
187
|
CURRENT=$(git branch --show-current)
|
|
214
188
|
echo "当前分支: $CURRENT | 主分支: $MAIN_BRANCH"
|
|
215
189
|
```
|
|
190
|
+
`$CURRENT` = `$MAIN_BRANCH` → ⛔ HARD_STOP,返回重新选择
|
|
191
|
+
`$CURRENT` ≠ `$MAIN_BRANCH` → 🔴 USER_GATE: 确认分支状态正确
|
|
192
|
+
|
|
193
|
+
> [HARD_STOP] **未通过验证或用户未确认时,禁止执行步骤 4-9。**
|
|
216
194
|
|
|
217
|
-
|
|
218
|
-
- `$CURRENT` ≠ `$MAIN_BRANCH` → 验证通过,展示分支状态供用户确认
|
|
195
|
+
3.5. **opsx:new 目录冲突预检**(⛔ PRECONDITION_FAIL,task #12)
|
|
219
196
|
|
|
220
|
-
|
|
221
|
-
>
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
197
|
+
```bash
|
|
198
|
+
if [ -d "openspec/changes/<name>" ]; then
|
|
199
|
+
echo "⛔ PRECONDITION_FAIL: openspec/changes/<name> 已存在"
|
|
200
|
+
echo " 可能原因:name 已被占用 / 旧 change 残留 / 多 session 并发"
|
|
201
|
+
echo " 禁止:agent 自动覆盖(rm -rf)或自动复用——可能丢失用户既有工作"
|
|
202
|
+
fi
|
|
203
|
+
```
|
|
226
204
|
|
|
227
|
-
|
|
205
|
+
🔴 USER_GATE: 选择处理路径
|
|
206
|
+
- (a) 改用其他 name → 回步骤 1 重新建议 change name
|
|
207
|
+
- (b) 接续已有 change → 退出 start,引导用户跑 `/alloy:start`(无 topic)触发"接续"路径
|
|
208
|
+
- (c) 中止本次 /alloy:start
|
|
228
209
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
- 已在 feature 分支上就跳过整个步骤 3——仍需确认当前分支名并记录
|
|
232
|
-
- 用户没回复就继续——分支状态必须用户确认
|
|
210
|
+
> [HARD_STOP] agent 不得自动选 (a) / (b) / (c)——必须由用户明确决策。
|
|
211
|
+
> 违反字面 = 违反精神:哪怕"目录看起来是空的"或"看起来是上次中断的",也禁 agent 自动复用。
|
|
233
212
|
|
|
234
|
-
4. **调用 `/opsx:new <name>`** 创建 change
|
|
213
|
+
4. **调用 `/opsx:new <name>`** 创建 change 目录(前置:步骤 3 ③ 验证已通过 + 步骤 3.5 目录冲突已解决)
|
|
235
214
|
|
|
236
|
-
|
|
215
|
+
调用后验证创建结果:
|
|
216
|
+
```bash
|
|
217
|
+
if [ ! -f "openspec/changes/<name>/.alloy.yaml" ]; then
|
|
218
|
+
echo "⛔ PRECONDITION_FAIL: /opsx:new 创建失败——.alloy.yaml 缺失"
|
|
219
|
+
echo " 退出 skill 让用户排查 opsx 命令"
|
|
220
|
+
exit 1
|
|
221
|
+
fi
|
|
222
|
+
```
|
|
237
223
|
|
|
238
|
-
5.
|
|
224
|
+
5. **批量记录技能使用:**
|
|
239
225
|
```bash
|
|
240
226
|
alloy _skill log openspec/changes/<name> start opsx:explore && \
|
|
241
227
|
alloy _skill log openspec/changes/<name> start superpowers:brainstorming && \
|
|
242
228
|
alloy _skill log openspec/changes/<name> start opsx:new
|
|
243
229
|
```
|
|
244
230
|
|
|
245
|
-
6. **写入 state
|
|
231
|
+
6. **写入 state:**
|
|
246
232
|
```bash
|
|
247
233
|
alloy _state init openspec/changes/<name>
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
**记录阶段启动时间:**
|
|
251
|
-
```bash
|
|
252
234
|
alloy _state merge openspec/changes/<name> phase_timings "{\"start\":{\"started_at\":\"$(date '+%Y-%m-%d %H:%M:%S')\"}}"
|
|
253
235
|
```
|
|
254
236
|
|
|
255
|
-
7.
|
|
237
|
+
7. **记录分支信息:**
|
|
256
238
|
```bash
|
|
257
239
|
alloy _state write openspec/changes/<name> feature_branch <branch-name>
|
|
258
240
|
alloy _state write openspec/changes/<name> worktree null
|
|
259
241
|
```
|
|
260
242
|
|
|
261
|
-
8.
|
|
243
|
+
8. **生成 `draft.md`** 到 `openspec/changes/<name>/draft.md`
|
|
262
244
|
|
|
263
|
-
**draft.md
|
|
245
|
+
**draft.md 审查窗口——start 阶段唯一的制品闸门:**
|
|
264
246
|
|
|
265
247
|
> 制品 draft ✓ 完成
|
|
266
|
-
>
|
|
267
248
|
> [展示 draft.md 完整内容]
|
|
268
|
-
>
|
|
269
|
-
> → (a) 确认,锁定 draft 并完成 start 阶段
|
|
270
|
-
> → (b) 需要调整 — 回到 brainstorming 重新讨论
|
|
271
|
-
|
|
272
|
-
- **选 (a)**:继续步骤 9,hash 锁定 + commit
|
|
273
|
-
- **选 (b)**:不生成文件、不 commit。回到 Step 2/2 的 brainstorming,基于用户反馈重新讨论方案。brainstorming 完成后重新生成 draft.md,再次进入此审查窗口
|
|
249
|
+
> 🔴 USER_GATE: 确认锁定 draft(确认并继续提交 / 需要调整回 brainstorming)
|
|
274
250
|
|
|
275
|
-
|
|
276
|
-
- 只问"看起来可以吗?"不展示 draft.md 实际内容
|
|
277
|
-
- 用户说"还行"、"可以"就跳过——必须明确选 (a) 或 (b)
|
|
278
|
-
- 把 brainstorming 阶段的方案确认等同于 draft.md 审查——brainstorming 确认的是概念,draft.md 审查的是最终文本
|
|
251
|
+
选确认 → 步骤 9;选调整 → 回到 Step 2/2 brainstorming。
|
|
279
252
|
|
|
280
|
-
|
|
253
|
+
9. **提交——仅用户确认锁定后,执行以下 2 个 commit:**
|
|
281
254
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
**alloy init 基础设施提交:**
|
|
255
|
+
**commit 1/2——基础设施(幂等,已提交则跳过;§5.2.1 git add 限路径):**
|
|
285
256
|
```bash
|
|
286
257
|
git add .claude/ .gitignore openspec/config.yaml openspec/schemas/ 2>/dev/null
|
|
287
258
|
[ -f CLAUDE.md ] && git add CLAUDE.md 2>/dev/null
|
|
288
259
|
git diff --cached --quiet || git commit -m "chore: alloy init 项目初始化"
|
|
289
260
|
```
|
|
290
|
-
已提交过则自动跳过。`.superpowers/` 已在 `.gitignore` 中忽略,不入仓库。
|
|
291
261
|
|
|
292
|
-
|
|
262
|
+
**commit 2/2——draft hash-lock + .alloy.yaml 变更(§5.2.1 git add 限路径):**
|
|
293
263
|
```bash
|
|
294
264
|
COMPLETED_AT=$(date "+%Y-%m-%d %H:%M:%S")
|
|
295
265
|
alloy _state merge openspec/changes/<name> phase_timings "{\"start\":{\"completed_at\":\"${COMPLETED_AT:-$(date '+%Y-%m-%d %H:%M:%S')}\"}}"
|
|
@@ -301,6 +271,8 @@ brainstorming 每个问题都是沟通成本。使用平台的交互式提示工
|
|
|
301
271
|
git commit -m "docs(<name>): draft 已确认"
|
|
302
272
|
```
|
|
303
273
|
|
|
274
|
+
前面步骤写入的 `.alloy.yaml` 变更在 draft commit 中一并提交。
|
|
275
|
+
|
|
304
276
|
---
|
|
305
277
|
|
|
306
278
|
### 完成
|
|
@@ -308,42 +280,21 @@ brainstorming 每个问题都是沟通成本。使用平台的交互式提示工
|
|
|
308
280
|
```
|
|
309
281
|
┌──────────────────────────────────────┐
|
|
310
282
|
│ Alloy [1/5] · Phase: Start — DONE │
|
|
311
|
-
│ 启动时间:
|
|
312
|
-
│ 完成时间:
|
|
313
|
-
│ 耗时:
|
|
283
|
+
│ 启动时间: phase_timings.start.started_at
|
|
284
|
+
│ 完成时间: phase_timings.start.completed_at
|
|
285
|
+
│ 耗时: completed_at - started_at
|
|
314
286
|
└──────────────────────────────────────┘
|
|
315
287
|
|
|
316
|
-
→ Change: <name>
|
|
317
|
-
→
|
|
318
|
-
|
|
319
|
-
所有制品已生成并锁定:
|
|
320
|
-
|
|
321
|
-
制品 状态 Hash 创建时间
|
|
322
|
-
────────────── ──── ──────────── ───────────────────
|
|
323
|
-
draft ✓ <hash> <timestamp>
|
|
324
|
-
|
|
325
|
-
准备好后,运行 /alloy:plan 进入规划阶段。
|
|
288
|
+
→ Change: <name> Phase: started
|
|
289
|
+
→ 制品: draft ✓
|
|
326
290
|
```
|
|
327
291
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
- 不要自动运行 `/alloy:plan` 或加载 `alloy-plan` 技能
|
|
333
|
-
- 不要生成 proposal.md、design.md、specs/、tasks.md、plans.md 或任何 plan 阶段制品
|
|
334
|
-
- 不要调用 `opsx:continue` 或 `superpowers:writing-plans`
|
|
335
|
-
- 不要因为"用户没回复"而继续——沉默 ≠ 授权
|
|
336
|
-
- 不要因为"这样更高效"而替用户做决定——用户必须自己发起下一阶段
|
|
292
|
+
> [HARD_STOP] **start 阶段到此结束。**
|
|
293
|
+
> 不要自动运行 `/alloy:plan`,不要生成 plan 阶段制品,不要调用 `opsx:continue` 或 `writing-plans`。
|
|
294
|
+
> 违反字面 = 违反精神:哪怕"用户上次也是接 plan 这次猜跳过 USER_GATE"或"draft 已锁定流程很顺",也算违反 Iron Law(NO AUTO ADVANCE)。
|
|
295
|
+
> **你的唯一操作:展示完成信息,等待用户输入下一个命令。**
|
|
337
296
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
---
|
|
341
|
-
|
|
342
|
-
## 闸门规则
|
|
343
|
-
|
|
344
|
-
- **git add 只用精确路径** — 永远不用 `-A`、`-a`、`.`。
|
|
345
|
-
start 阶段只 add `openspec/changes/<name>/` 和 init 基础设施文件(`.claude/` `.gitignore` `openspec/config.yaml` `openspec/schemas/`);反例:`git add -A` 会把临时文件一起提交
|
|
346
|
-
- **draft.md 必须在 change 目录内** — 不在项目根目录产生临时文件
|
|
297
|
+
> **§5.2.3 路径 B 边界说明:** start 是 phase 推进起点(无前序 phase),phase=started 写入失败时降级路径只有"重跑 /alloy:start"——不存在 phase 回退场景。本阶段无 §5.2.3 适用空间。
|
|
347
298
|
|
|
348
299
|
---
|
|
349
300
|
|
|
@@ -352,27 +303,31 @@ brainstorming 每个问题都是沟通成本。使用平台的交互式提示工
|
|
|
352
303
|
```
|
|
353
304
|
┌──────────────────────────────────────┐
|
|
354
305
|
│ Alloy [1/5] · Phase: Start │
|
|
355
|
-
│ 启动时间: <TIMESTAMP>
|
|
306
|
+
│ 启动时间: <TIMESTAMP>
|
|
356
307
|
└──────────────────────────────────────┘
|
|
357
308
|
```
|
|
358
309
|
|
|
359
|
-
|
|
310
|
+
扫描项目上下文(README、代码、requirement.md 等)。
|
|
311
|
+
|
|
312
|
+
**有上下文:** 总结项目信息,给 2-3 个建议方向,帮用户明确要做什么。
|
|
360
313
|
|
|
361
|
-
|
|
314
|
+
**空项目:** "项目较新,无上下文。请用 `/alloy:start <topic>` 重新调用,进入完整需求设计流程。"
|
|
362
315
|
|
|
363
|
-
|
|
316
|
+
> 必须让用户重新输入 `/alloy:start <topic>`——只有重新调用命令,alloy:start 技能才会被重新加载。仅输入 topic 文本会导致脱离编排框架,关键闸门被跳过。
|
|
364
317
|
|
|
365
|
-
|
|
318
|
+
**自由探索发现用户有明确 topic 后:**
|
|
366
319
|
|
|
367
|
-
|
|
320
|
+
🔴 USER_GATE: 检测到明确功能需求,请选择:
|
|
321
|
+
- (a) 以 "<topic>" 进入全新开始(请输入 `/alloy:start <topic>` 正式开始)
|
|
322
|
+
- (b) 继续自由探索
|
|
368
323
|
|
|
369
|
-
|
|
324
|
+
选 (a) 时输出提示文本,Agent 不得直接跳转到"全新开始"流程。
|
|
370
325
|
|
|
371
326
|
---
|
|
372
327
|
|
|
373
328
|
## 强制新建(--new <topic>)
|
|
374
329
|
|
|
375
|
-
无论是否有活跃 change,直接走"全新开始"流程。多个 change 可并行 planning,但不能同时 apply
|
|
330
|
+
无论是否有活跃 change,直接走"全新开始"流程。多个 change 可并行 planning,但不能同时 apply。
|
|
376
331
|
|
|
377
332
|
---
|
|
378
333
|
|
|
@@ -381,59 +336,44 @@ brainstorming 每个问题都是沟通成本。使用平台的交互式提示工
|
|
|
381
336
|
```
|
|
382
337
|
┌──────────────────────────────────────┐
|
|
383
338
|
│ Alloy [1/5] · Phase: Start │
|
|
384
|
-
│ 启动时间:
|
|
339
|
+
│ 启动时间: phase_timings.start.started_at 或 created_at
|
|
385
340
|
└──────────────────────────────────────┘
|
|
386
341
|
|
|
387
|
-
→ 检测到活跃 change:<name
|
|
388
|
-
→
|
|
389
|
-
→ 已完成制品:<列出已有文件>
|
|
342
|
+
→ 检测到活跃 change:<name>(phase: <phase>)
|
|
343
|
+
→ 已完成制品:<列出>
|
|
390
344
|
→ 下一步:<建议操作>
|
|
391
345
|
```
|
|
392
346
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
先读取 `.alloy.yaml` 获取 phase 和 worktree 字段,再检查文件系统确认实际制品状态。
|
|
396
|
-
|
|
397
|
-
展示检测结果后,根据 phase 和制品状态决定路由:
|
|
347
|
+
读取 `.alloy.yaml` + 文件系统确认制品状态,按 phase 路由:
|
|
398
348
|
|
|
399
349
|
| phase | 制品状态 | 路由 |
|
|
400
350
|
|-------|---------|------|
|
|
401
|
-
| started | proposal.md 存在 | alloy-plan
|
|
402
|
-
| started |
|
|
403
|
-
| started |
|
|
404
|
-
| planned | — |
|
|
405
|
-
| applied | — |
|
|
406
|
-
| archived | — |
|
|
407
|
-
| finished | — |
|
|
408
|
-
|
|
409
|
-
**实现方式:**
|
|
410
|
-
|
|
411
|
-
- **需自动加载命令时**(proposal.md 存在 → plan、planned → apply 等):输出对应命令文件的完整指令(`commands/alloy/plan.md` / `apply.md` / `archive.md` / `finish.md`),将 change name 和检测到的进度信息作为上下文传入。Agent 无缝进入对应阶段。
|
|
412
|
-
- **需用户选择时**(draft 已确认、proposal 不存在):先校验 draft hash:
|
|
413
|
-
```bash
|
|
414
|
-
alloy _record check openspec/changes/<name> draft
|
|
415
|
-
```
|
|
416
|
-
hash 有效 → 展示选择:"draft 已确认。 (a) 进入 plan 阶段 (b) 回到 brainstorming 修改需求"。等用户选择后执行对应路由。
|
|
417
|
-
hash 不匹配 → 走"draft 不存在或 hash 不匹配"路径。
|
|
418
|
-
|
|
419
|
-
一致性检查(双向):
|
|
420
|
-
- worktree 字段有值但磁盘路径不存在 → ⚠️ "worktree 残留:.alloy.yaml 声称有 worktree 但磁盘不存在"
|
|
421
|
-
- worktree 字段为 null 但 `.worktrees/<name>/` 目录存在 → ⚠️ "worktree 孤儿:磁盘存在 worktree 但 .alloy.yaml 未记录,建议手动验证并更新状态"
|
|
422
|
-
- 发现孤儿 worktree 时,询问用户是否修复 .alloy.yaml:`alloy _state write openspec/changes/<name> worktree ".worktrees/<name>"`
|
|
351
|
+
| started | proposal.md 存在 | 🔴 USER_GATE: 选择继续规划(alloy-plan) / 回需求讨论(重新 start) |
|
|
352
|
+
| started | draft.md 存在且 hash 有效 | 🔴 USER_GATE: 选择进 plan / 回 brainstorming |
|
|
353
|
+
| started | draft.md 缺失或 hash 不匹配 | 重新 brainstorming |
|
|
354
|
+
| planned | — | 🔴 USER_GATE: 确认进入 apply 阶段(继续 / 查看状态 / 放弃 change) |
|
|
355
|
+
| applied | — | 🔴 USER_GATE: 确认进入 archive 阶段(继续 / 查看状态 / 放弃 change) |
|
|
356
|
+
| archived | — | 🔴 USER_GATE: 确认进入 finish 阶段(继续 / 查看状态) |
|
|
357
|
+
| finished | — | 工作流已完成 |
|
|
423
358
|
|
|
424
|
-
|
|
359
|
+
**所有 🔴 USER_GATE 的选项模板(同款语义节点,6 phase 共用):**
|
|
360
|
+
- (a) 进入 `<目标阶段>` 继续
|
|
361
|
+
- (b) 查看状态(/alloy:status)
|
|
362
|
+
- (c) 放弃此 change(/alloy:discard)——仅 planned/applied 阶段可选
|
|
425
363
|
|
|
426
|
-
|
|
364
|
+
**自动跳转仅限**:用户明确选择 (a) 后才加载目标命令。
|
|
427
365
|
|
|
428
|
-
|
|
429
|
-
┌──────────────────────────────────────┐
|
|
430
|
-
│ Alloy [1/5] · Phase: Start │
|
|
431
|
-
│ 启动时间: 从 phase_timings.start.started_at 读取,若无则从 created_at 读取 │
|
|
432
|
-
└──────────────────────────────────────┘
|
|
366
|
+
**需自动加载时:** 输出对应命令文件完整指令,将 change name 和进度信息传入。
|
|
433
367
|
|
|
434
|
-
|
|
435
|
-
```
|
|
368
|
+
**需用户选择时:** 先校验 draft hash(`alloy _record check openspec/changes/<name> draft`),hash 有效 → 展示选择。
|
|
436
369
|
|
|
437
|
-
|
|
370
|
+
一致性检查:
|
|
371
|
+
- worktree 字段有值但路径不存在 → ⚠️ WARN 残留
|
|
372
|
+
- worktree 为 null 但 `.worktrees/<name>/` 存在 → ⚠️ WARN 孤儿,询问是否修复
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## 多选(有多个活跃 change)
|
|
438
377
|
|
|
439
378
|
列出所有活跃 change(名称 + phase + 制品状态),让用户选择接续哪个,或 `--new <topic>` 开新 change。
|
|
379
|
+
|