@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/apply.md
CHANGED
|
@@ -3,376 +3,216 @@ name: "Alloy: Apply"
|
|
|
3
3
|
description: Alloy 执行阶段 - plan 完成后进入
|
|
4
4
|
category: Workflow
|
|
5
5
|
tags: [alloy, workflow]
|
|
6
|
+
spec: 01-product-spec/03-apply-spec.md
|
|
7
|
+
behaviors:
|
|
8
|
+
preconditions: 11
|
|
9
|
+
hard_stops: 8
|
|
10
|
+
user_gates: 8
|
|
11
|
+
warns: 3
|
|
12
|
+
artifacts: [verify, retrospective]
|
|
13
|
+
transitions_to: applied
|
|
14
|
+
external_calls: [opsx:verify, superpowers:using-git-worktrees, superpowers:subagent-driven-development, superpowers:executing-plans, superpowers:test-driven-development, superpowers:verification-before-completion, superpowers:requesting-code-review]
|
|
6
15
|
---
|
|
7
16
|
|
|
8
17
|
# alloy-apply
|
|
9
18
|
|
|
10
|
-
你是 Alloy 的执行阶段编排器。按
|
|
19
|
+
你是 Alloy 的执行阶段编排器。按 plans.md 任务实现,内部遵循 TDD,执行完毕自动验证和复盘。
|
|
11
20
|
|
|
12
|
-
|
|
21
|
+
```
|
|
22
|
+
[HARD_STOP] NO CODE WITHOUT TDD + NO ARTIFACT EDITING
|
|
23
|
+
先写测试再写代码;已生成制品禁止直接编辑,必须重新生成
|
|
24
|
+
违反字面 = 违反精神:哪怕"小改一行 case 不补测试"或"直接编辑 verify.md 换措辞",也算违反 Iron Law
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**核心原则:先 TDD 再代码,先验证再复盘。** 所有阶段制品(verify / retrospective)以 hash-lock + 单独 commit 入 records,禁直接编辑。
|
|
28
|
+
|
|
29
|
+
**交互规则:** `🔴 STOP` 等价 `USER_GATE`,必须用 `AskUserQuestion`(`commands/alloy/references/interaction-style.md`,含"沉默 ≠ 授权"通用禁令——禁批量打包、禁基于 diff 短/无 conflict 跳过、禁 agent 回填精确字符串)。跳过任何 USER_GATE = 违反 Iron Law。
|
|
13
30
|
|
|
14
|
-
**状态符号:**
|
|
31
|
+
**状态符号:** `⛔` = HARD_STOP / PRECONDITION_FAIL,`🔴` = USER_GATE,`⚠️` = WARN(视觉规范 §七)。
|
|
15
32
|
|
|
16
|
-
|
|
33
|
+
**调用外部命令或技能前,先输出标题和状态描述,再执行操作。**
|
|
17
34
|
|
|
18
|
-
|
|
35
|
+
**捕获阶段启动时间**(幂等,重入时返回已有值):
|
|
19
36
|
```bash
|
|
20
37
|
PHASE_START=$(alloy _state timestamp ensure openspec/changes/<name> apply)
|
|
21
38
|
```
|
|
22
39
|
|
|
23
40
|
---
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
- precheck 发现技能缺失但继续执行——"先跑着,后面可能用不到"——后面会静默丢失 TDD 或 code review
|
|
27
|
-
- 验证失败后直接改代码跳回验证,不经过 SDD——丢失了 TDD 安全网
|
|
28
|
-
- retrospective 在没有 verify.md 的情况下生成——复盘建立在不可靠的基础上
|
|
29
|
-
- 在主分支上创建 worktree——"start 已经确认过主分支了"——plan 阶段的 commit 在 feature 分支上,worktree 基于 main 会丢失这些 commit
|
|
30
|
-
- feature_branch 为 null 时静默回退——"回退路径是设计的容错"——null 是状态异常,回退值可能与实际分支不一致
|
|
31
|
-
- 跳过分支验证闸门直接加载 using-git-worktrees——"技能内部会处理 base ref"——技能不知道你的 feature_branch 是什么
|
|
42
|
+
### Red Flags(第三层防御——任一借口出现即 STOP)
|
|
32
43
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
以下任何一个念头出现,都意味着闸门正在被绕过:
|
|
44
|
+
主文件保留 5 条核心借口,完整 12 条见 `commands/alloy/references/apply-rationalizations.md`。
|
|
36
45
|
|
|
37
46
|
| 借口 | 现实 |
|
|
38
47
|
|------|------|
|
|
39
|
-
| "
|
|
40
|
-
| "
|
|
41
|
-
| "
|
|
42
|
-
| "
|
|
43
|
-
| "
|
|
44
|
-
| "用户很急,跳过 review 吧" | 跳过 review = 跳过代码质量闸门。急不是绕过流程的理由。 |
|
|
45
|
-
| "start 阶段已经确认过主分支了" | 配置可能已变,确认只需 2 秒。跳过确认 = 在错误的 base 上创建 worktree。 |
|
|
46
|
-
| "feature_branch 是 null,用回退值就行" | null 是状态异常,不是设计的容错。回退值可能与实际分支不一致——交叉验证后才能用。 |
|
|
47
|
-
| "当前在 main 上,直接建 worktree 吧" | 主分支上创建 worktree 丢失 feature 分支的 plan commit。必须先切到 feature 分支。 |
|
|
48
|
-
| "using-git-worktrees 技能内部会处理 base ref" | 技能不知道你的 feature_branch 是什么。base ref 由 apply.md 决定,不是下游技能。 |
|
|
49
|
-
| "先建 worktree 再问用户要不要" | 必须在 consent 前等待。consent 是 before worktree 创建,不是 after。先建后问 = 剥夺用户选择权。加载技能后立即停手,等用户明确回复。 |
|
|
48
|
+
| "先写代码再补测试" | TDD 次序不可颠倒。提速靠并行子任务,不靠砍测试(Iron Law 第一层)。 |
|
|
49
|
+
| "用户要改需求,直接改" | 需求变更必须走 tasks.md checkbox 闸门。已编码→开新 change,未编码→回溯,禁直接改 plans.md。 |
|
|
50
|
+
| "verify.md 措辞不太顺,直接编辑改一下" | 制品禁直接编辑——任何变更必须重新生成 + 重新 hash-lock。违反字面 = 违反精神。 |
|
|
51
|
+
| "verify FAIL 是小问题,retro 写'已知 FAIL'继续" | FAIL 必须修复回到 Step 2。带 FAIL 进 archive 阶段 = spec 与代码偏差永久封存。 |
|
|
52
|
+
| "single-commit 修复不需要 retrospective,自动跳过" | retrospective 跳过判定必须 USER_GATE,agent 不得自动选"跳过"(task #17)。 |
|
|
50
53
|
|
|
51
54
|
## 前置检查
|
|
52
55
|
|
|
53
|
-
1. 确认 `plans.md` 存在于 change 目录,不存在则报错
|
|
54
|
-
2. 通过 `alloy _guard` 确认 change 的 phase:
|
|
55
|
-
```bash
|
|
56
|
-
alloy _guard openspec/changes/<name> applied
|
|
57
|
-
```
|
|
58
|
-
若 guard 报错说明 phase 转换不合法——读取 `commands/alloy/references/phase-routing.md` 按路由表自动跳转。当前 phase=planned 或 applied 时 precheck 通过(applied 为断点重入)。
|
|
59
|
-
3. 确认当前目录在 git 仓库内:
|
|
60
|
-
```bash
|
|
61
|
-
git rev-parse --git-dir
|
|
62
|
-
```
|
|
63
|
-
若命令成功 → 继续。
|
|
64
|
-
若命令失败 → HARD STOP:"项目还不是 git 仓库。请先运行 `/alloy:start` 完成初始化(包含 git init)。"
|
|
65
|
-
4. **Skill 预检:** 确认以下依赖可用:
|
|
66
|
-
cmd: opsx/verify
|
|
67
|
-
skill: using-git-worktrees subagent-driven-development executing-plans test-driven-development requesting-code-review verification-before-completion
|
|
68
|
-
|
|
69
|
-
读取 `commands/alloy/references/skill-precheck.md` 了解检测方法。任一缺失 → 输出缺失列表 → 引导 `alloy init` → STOP。**不存在降级处理。** 技能是闸门,不是加速器——有则用,无则停。
|
|
70
|
-
|
|
71
56
|
```
|
|
72
57
|
┌──────────────────────────────────────┐
|
|
73
58
|
│ Alloy [3/5] · Phase: Apply │
|
|
74
59
|
│ 启动时间: $PHASE_START │
|
|
75
60
|
└──────────────────────────────────────┘
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### [Step 0/5] 前置检查
|
|
64
|
+
|
|
65
|
+
**1. plans.md 存在(PRECONDITION_FAIL):** 文件不存在 → ⛔ `[PRECONDITION_FAIL] plans.md 不存在,apply 拒绝执行。请先运行 /alloy:plan 完成 plan 阶段。` 然后退出 skill。
|
|
76
66
|
|
|
77
|
-
|
|
78
|
-
后续步骤写入 worktree 的路径和分支名也会进入此快照 commit,确保 worktree 内能看到完整状态。
|
|
67
|
+
**2. phase 路由(PRECONDITION_FAIL):**
|
|
79
68
|
|
|
80
69
|
```bash
|
|
81
|
-
|
|
82
|
-
git diff --cached --quiet || git commit -m "chore(<name>): apply 阶段开始前状态快照"
|
|
70
|
+
alloy _guard precheck openspec/changes/<name> planned,applied
|
|
83
71
|
```
|
|
84
72
|
|
|
85
|
-
|
|
73
|
+
phase=planned 或 applied 时通过(applied 为断点重入)。不匹配 → ⛔ `[PRECONDITION_FAIL]`,读取 `commands/alloy/references/phase-routing.md` 自动跳转。
|
|
86
74
|
|
|
87
|
-
|
|
75
|
+
**3. git 仓库(PRECONDITION_FAIL):**
|
|
88
76
|
|
|
89
|
-
|
|
77
|
+
```bash
|
|
78
|
+
git rev-parse --git-dir
|
|
79
|
+
```
|
|
90
80
|
|
|
91
|
-
|
|
81
|
+
失败 → ⛔ `[PRECONDITION_FAIL] 项目还不是 git 仓库。请先运行 /alloy:start 完成初始化。`
|
|
92
82
|
|
|
93
|
-
|
|
83
|
+
**4. Skill 预检(PRECONDITION_FAIL):** cmd: opsx/verify, skill: using-git-worktrees subagent-driven-development executing-plans test-driven-development requesting-code-review verification-before-completion
|
|
94
84
|
|
|
95
|
-
|
|
85
|
+
读取 `commands/alloy/references/skill-precheck.md` 检测。任一缺失 → ⛔ `[PRECONDITION_FAIL] skill 缺失,引导 alloy init,不存在降级处理`。agent 不得自行模拟缺失 skill 的行为。
|
|
96
86
|
|
|
97
|
-
|
|
87
|
+
**5. 多 change 并行 apply 检测(WARN,task #14):** apply 单 change 串行(subagent 内部并行 OK)——同期多个 change 同时 apply 会导致 git 操作竞争(branch 切换、worktree 创建、commit 写入相互干扰)。
|
|
98
88
|
|
|
99
|
-
apply
|
|
89
|
+
读取 `commands/alloy/references/apply-precheck.md` 执行检测。WARN 不阻断——仅提示。
|
|
100
90
|
|
|
101
|
-
|
|
91
|
+
提交前置状态(worktree 创建前确保 .alloy.yaml 变更已落地):
|
|
102
92
|
```bash
|
|
103
|
-
|
|
93
|
+
# §5.2.1: git add 限路径,禁 -A 无路径
|
|
94
|
+
git add openspec/changes/<name>/.alloy.yaml
|
|
95
|
+
git diff --cached --quiet || git commit -m "chore(<name>): apply 阶段开始前状态快照"
|
|
104
96
|
```
|
|
105
97
|
|
|
106
|
-
|
|
107
|
-
- 返回 > 0(有已勾选任务)→ 编码已开始,拒绝回溯
|
|
98
|
+
前置检查通过:plans.md ✓ phase ✓ git ✓ 技能 ✓
|
|
108
99
|
|
|
109
|
-
|
|
100
|
+
> 共 5 步:隔离 → 任务实现 → 代码验证 → 制品验证 → 复盘
|
|
110
101
|
|
|
111
|
-
|
|
112
|
-
> → (b) 取消,继续 apply
|
|
102
|
+
---
|
|
113
103
|
|
|
114
|
-
|
|
104
|
+
## 需求变更闸门
|
|
115
105
|
|
|
116
|
-
|
|
106
|
+
用户提出需求/设计变更时,以编码是否已开始为分界线:
|
|
117
107
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
108
|
+
```bash
|
|
109
|
+
grep -c '\[x\]' openspec/changes/<name>/tasks.md
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- **返回 0(未编码):** 🔴 USER_GATE(必须 AskUserQuestion): 检测到需求变更,tasks 尚未编码。选择处理路径:
|
|
113
|
+
- (a) 回溯清理 plan 制品,回到 brainstorming
|
|
114
|
+
- (b) 取消变更,继续 apply
|
|
115
|
+
|
|
116
|
+
选 (a):清理 plan 制品 → 回到 brainstorming(plan.md 的回溯清理步骤)。
|
|
117
|
+
选 (b):继续当前 apply 流程。
|
|
122
118
|
|
|
123
|
-
|
|
119
|
+
- **返回 > 0(已编码):** 🔴 USER_GATE(必须 AskUserQuestion): 检测到需求变更,tasks 已有编码完成项。选择处理路径:
|
|
120
|
+
- (a) 开新 change 处理变更(引导 `/alloy:start <建议名称>`)
|
|
121
|
+
- (b) 取消变更,继续 apply
|
|
124
122
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
- 在同一 change 上多次反复变更需求——每次变更都应经过闸门判断
|
|
123
|
+
选 (a):引导用户运行 `/alloy:start <建议名称>` 开新 change。
|
|
124
|
+
选 (b):继续当前 apply 流程。
|
|
125
|
+
|
|
126
|
+
> 违反字面 = 违反精神:禁直接编辑 plans.md "顺手"承载需求变更——必须走 (a) 回溯或开新 change,否则 plans hash 锁定形同虚设。
|
|
130
127
|
|
|
131
128
|
## 执行步骤
|
|
132
129
|
|
|
133
130
|
### [Step 1/5] 隔离环境设置
|
|
134
131
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
alloy _state read openspec/changes/<name> worktree
|
|
138
|
-
```
|
|
132
|
+
> [HARD_STOP §3.5.1] worktree / branch 操作链路上严禁 agent 自动 `git worktree remove --force` / `git worktree prune --force` / `git branch -D` / `rm -rf .claude/worktrees/<name>` / `git reset --hard` 任意一个清场。
|
|
133
|
+
> 违反字面 = 违反精神:哪怕"残留 worktree 看起来空,删了让流程继续",也算违反禁令——必须 USER_GATE。
|
|
139
134
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
worktree 值: 有效路径 → 路径不存在 → ⚠️ 残留记录,重新处理
|
|
144
|
-
worktree 值: "skipped" → ✓ 用户选择不创建,跳过此步骤
|
|
145
|
-
worktree 值: null(从未写入) → ⚠️ 尚未决定,加载 using-git-worktrees
|
|
135
|
+
**幂等检查:**
|
|
136
|
+
```bash
|
|
137
|
+
alloy _guard worktree-status openspec/changes/<name>
|
|
146
138
|
```
|
|
147
139
|
|
|
148
|
-
|
|
140
|
+
- `done:<path>:<branch>` → ✓ 已完成,跳过
|
|
141
|
+
- `skipped` → ✓ 用户选择不创建,跳过
|
|
142
|
+
- `pending` → 加载 using-git-worktrees
|
|
143
|
+
- `stale:<path>` → ⚠️ WARN 残留记录,让用户决策清理或重用,agent 不得自动 `git worktree prune`(§3.5.1)
|
|
149
144
|
|
|
150
|
-
|
|
145
|
+
**分支验证闸门(PRECONDITION_FAIL)**——加载 using-git-worktrees 前必须通过;base ref 取决于当前分支,错误 base = plan 阶段 commit 丢失:
|
|
151
146
|
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
>
|
|
155
|
-
> 当前在 `<feature_branch>`。未在隔离 worktree 中。
|
|
156
|
-
>
|
|
157
|
-
> 分支隔离的是提交历史,但同一时间只能有一个分支在工作目录里。
|
|
158
|
-
> Worktree 隔离的是工作目录——每个 worktree 有独立的文件副本,可同时 checkout 不同分支。
|
|
159
|
-
>
|
|
160
|
-
> 如果你的 feature 开发期间要切到其他分支(如修紧急 bug、切 main 查东西),
|
|
161
|
-
> worktree 让你无需 stash/commit 当前进度,直接进另一个目录操作。
|
|
162
|
-
>
|
|
163
|
-
> 正在验证分支位置...
|
|
147
|
+
```bash
|
|
148
|
+
alloy _guard branch-position openspec/changes/<name>
|
|
164
149
|
```
|
|
165
150
|
|
|
166
|
-
|
|
151
|
+
- `on-feature` → ✓ 位置正确
|
|
152
|
+
- `on-main` / `feature-missing` / `feature-lost:<branch>` / `on-other:<branch>` → ⛔ `[PRECONDITION_FAIL] 分支位置异常`:
|
|
153
|
+
- on-main:在主分支,不允许创建 worktree——plan 阶段 commit 在 feature 分支上
|
|
154
|
+
- feature-missing / feature-lost:feature_branch 状态记录与实际不符
|
|
155
|
+
- on-other:当前位于第三分支
|
|
167
156
|
|
|
168
|
-
|
|
157
|
+
详细分类与修复选项见 `commands/alloy/references/branch-validation.md`。**禁止 agent 自动 `git checkout` 切换或 `git branch -m` 重命名——可能丢弃用户未提交工作(§3.5.1)。**
|
|
169
158
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
- **在主分支上**(`CURRENT_BRANCH === MAIN_BRANCH`)→ HARD STOP:"当前在主分支 `<main_branch>`。不允许从主分支创建 worktree——plan 阶段的 commit 在 feature 分支上,worktree 会丢失这些变更。" → 必须 `git checkout <feature_branch>` 后再继续
|
|
178
|
-
- **当前分支 = feature_branch** → ✓ 位置正确,继续
|
|
179
|
-
- **feature_branch 为 null** → ⚠️ 状态异常,需修复:
|
|
180
|
-
```
|
|
181
|
-
.alloy.yaml 未记录 feature_branch。这通常是 start 阶段数据写入失败。
|
|
182
|
-
|
|
183
|
-
→ (a) 手动指定:输入分支名(如 feature/<name>)
|
|
184
|
-
→ (b) 使用当前分支 `<current_branch>` 作为 feature_branch
|
|
185
|
-
→ (c) 放弃,回退到 start 阶段修复
|
|
186
|
-
```
|
|
187
|
-
用户选择后,`alloy _state write openspec/changes/<name> feature_branch <用户确认的分支>`,然后继续。**null 是状态异常,不是设计的容错——不允许静默回退。**
|
|
188
|
-
- **当前分支 ≠ feature_branch** → 提示切换:
|
|
189
|
-
```
|
|
190
|
-
当前在 `<current_branch>`,但 feature_branch 记录为 `<feature_branch>`。
|
|
191
|
-
→ (a) 切换到 <feature_branch>(推荐)
|
|
192
|
-
→ (b) 使用当前分支 <current_branch>(更新 feature_branch 记录)
|
|
193
|
-
```
|
|
194
|
-
选 (a):`git checkout <feature_branch>` → 继续
|
|
195
|
-
选 (b):`alloy _state write openspec/changes/<name> feature_branch <current_branch>` → 继续
|
|
196
|
-
- **feature_branch 不存在本地** → ⚠️ 分支丢失:
|
|
197
|
-
```
|
|
198
|
-
feature_branch 记录为 `<feature_branch>`,但本地不存在此分支。
|
|
199
|
-
→ (a) 从远程拉取:git fetch origin <feature_branch> && git checkout <feature_branch>
|
|
200
|
-
→ (b) 手动指定其他分支
|
|
201
|
-
→ (c) 放弃,回退到 start 阶段修复
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**③ base ref 锁定:** 创建 worktree 时,必须基于 `feature_branch`(不是 HEAD,不是 main)。
|
|
205
|
-
|
|
206
|
-
分支验证闸门通过后,**先加载技能获取用户 consent(创建/跳过),不要在 consent 前创建 worktree。**
|
|
207
|
-
|
|
208
|
-
使用 Skill 工具加载 `superpowers:using-git-worktrees` 技能。传入参数:
|
|
209
|
-
|
|
210
|
-
> 工作目录偏好: .claude/worktrees/<name>
|
|
211
|
-
> 分支命名: worktree-<name>
|
|
212
|
-
> 基于: <feature_branch>
|
|
213
|
-
> **重要:** 仅使用技能的 Step 0(检测+consent 问询)。用户 consent 后,不要使用技能的 Step 1a(EnterWorktree)或 Step 1b(git fallback)创建方法——EnterWorktree 默认从 origin/main 分出,base ref 错误。改用下方的 "base ref 处理策略" 手动创建并进入。
|
|
214
|
-
|
|
215
|
-
技能加载后,Agent 按其内部指引执行 Step 0(检测+consent)。**必须等待用户明确选择(创建/跳过)后才能继续。**
|
|
216
|
-
|
|
217
|
-
**什么算"consent 没做到"(反例):**
|
|
218
|
-
- 技能加载后直接建 worktree,没等用户回复——"用户没拒绝就等于同意"是错误的
|
|
219
|
-
- 用户说"嗯"、"好吧"、"随便"就当成同意——模糊回复不等于明确同意
|
|
220
|
-
- 先 `git worktree add` 再加载技能——顺序反了,consent 必须在前
|
|
221
|
-
|
|
222
|
-
**技能加载后立即记录:**
|
|
223
|
-
```bash
|
|
224
|
-
alloy _skill log openspec/changes/<name> apply superpowers:using-git-worktrees
|
|
225
|
-
```
|
|
159
|
+
**主分支确认:** 读取 `commands/alloy/references/main-branch-detection.md`。若 `openspec/config.yaml` 已有 `alloy.main_branch`,直接用,跳过确认。
|
|
160
|
+
|
|
161
|
+
分支验证通过后,加载 `superpowers:using-git-worktrees` 技能获取用户 consent:
|
|
162
|
+
- 传入:工作目录偏好 `.claude/worktrees/<name>`,分支命名 `worktree-<name>`,基于 `<feature_branch>`
|
|
163
|
+
- **仅使用 Step 0(检测+consent)。不要用 Step 1a/1b 的创建方法——EnterWorktree 默认从 origin/main 分出,base ref 错误。**
|
|
164
|
+
- **必须等用户明确选择(创建/跳过)后才继续。模糊回复("嗯"、"好吧")不算同意。** 🔴 USER_GATE(必须 AskUserQuestion): 确认 worktree 选择(创建 / 跳过)。
|
|
226
165
|
|
|
227
|
-
**用户选择不创建:** 写入 `skipped`(非 null),跳过后续创建步骤:
|
|
228
166
|
```bash
|
|
229
|
-
alloy
|
|
167
|
+
alloy _skill log openspec/changes/<name> apply superpowers:using-git-worktrees
|
|
168
|
+
# _skill log 写入后必须 commit——git worktree add 基于 HEAD 创建,
|
|
169
|
+
# 不 commit 会导致此条记录在 worktree 中丢失
|
|
170
|
+
git add openspec/changes/<name>/.alloy.yaml
|
|
171
|
+
git diff --cached --quiet || git commit -m "chore(<name>): 记录 using-git-worktrees 技能使用"
|
|
230
172
|
```
|
|
231
173
|
|
|
232
|
-
|
|
174
|
+
**用户选择不创建:** `alloy _state write openspec/changes/<name> worktree skipped`,跳到 Step 1 完成框。
|
|
233
175
|
|
|
234
|
-
|
|
235
|
-
2. **回退:** 若 EnterWorktree 支持自定义 base ref(查看工具参数),直接使用并传入 feature_branch
|
|
176
|
+
**用户选择创建:** 手动创建确保正确 base ref。
|
|
236
177
|
|
|
237
|
-
|
|
178
|
+
**路径占用检查 + 创建后状态记录 + worktree 内分支锁定**:读取 `commands/alloy/references/apply-worktree.md`:
|
|
238
179
|
|
|
239
|
-
|
|
180
|
+
- 路径占用 → ⛔ PRECONDITION_FAIL + 🔴 USER_GATE(复用 / 重命名 / 中止)。**禁 agent 自动 `rm -rf` 或 `git worktree remove --force` 清场(§3.5.1)。**
|
|
181
|
+
- 路径未占用 → `git worktree add` 创建并 `EnterWorktree` 进入
|
|
182
|
+
- 创建后写入 worktree / worktree_branch / worktree_created_at 三字段并 commit(断点恢复)
|
|
183
|
+
- 进入后校验 HEAD == `worktree-<name>`(task #18);不一致 ⛔ PRECONDITION_FAIL,**禁 agent 自动 git checkout 切换。**
|
|
240
184
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
|
247
|
-
|
|
248
|
-
if [ "$GIT_DIR" != "$GIT_COMMON" ]; then
|
|
249
|
-
# 已在 worktree 中,获取实际路径和分支名
|
|
250
|
-
WORKTREE_PATH=$(cd "$(git rev-parse --show-toplevel)" 2>/dev/null && pwd -P)
|
|
251
|
-
WORKTREE_BRANCH=$(cd "$WORKTREE_PATH" && git branch --show-current)
|
|
252
|
-
alloy _state write openspec/changes/<name> worktree "$WORKTREE_PATH"
|
|
253
|
-
alloy _state write openspec/changes/<name> worktree_branch "$WORKTREE_BRANCH"
|
|
254
|
-
alloy _state write openspec/changes/<name> worktree_created_at "$(date '+%Y-%m-%d %H:%M:%S')"
|
|
255
|
-
echo " ✓ worktree 已记录: 分支=$WORKTREE_BRANCH 路径=$WORKTREE_PATH"
|
|
256
|
-
# commit 确保断点恢复时 state 不丢失
|
|
257
|
-
git add openspec/changes/<name>/.alloy.yaml
|
|
258
|
-
git diff --cached --quiet || git commit -m "chore(<name>): record worktree state"
|
|
259
|
-
else
|
|
260
|
-
# EnterWorktree 失败后的 git worktree fallback
|
|
261
|
-
# 优先检测 .claude/worktrees/(EnterWorktree 原生路径),回退 .worktrees/
|
|
262
|
-
WT_PATH=""
|
|
263
|
-
for CANDIDATE in ".claude/worktrees/<name>" ".worktrees/<name>"; do
|
|
264
|
-
if [ -d "$CANDIDATE" ]; then
|
|
265
|
-
WT_PATH=$(cd "$CANDIDATE" 2>/dev/null && pwd -P)
|
|
266
|
-
break
|
|
267
|
-
fi
|
|
268
|
-
done
|
|
269
|
-
if [ -n "$WT_PATH" ]; then
|
|
270
|
-
WORKTREE_BRANCH=$(cd "$WT_PATH" && git branch --show-current 2>/dev/null)
|
|
271
|
-
alloy _state write openspec/changes/<name> worktree "$WT_PATH"
|
|
272
|
-
alloy _state write openspec/changes/<name> worktree_branch "$WORKTREE_BRANCH"
|
|
273
|
-
alloy _state write openspec/changes/<name> worktree_created_at "$(date '+%Y-%m-%d %H:%M:%S')"
|
|
274
|
-
echo " ✓ worktree fallback 已记录: 分支=$WORKTREE_BRANCH 路径=$WT_PATH"
|
|
275
|
-
# 提交 source repo 的 state
|
|
276
|
-
git add openspec/changes/<name>/.alloy.yaml
|
|
277
|
-
git diff --cached --quiet || git commit -m "chore(<name>): record worktree state"
|
|
278
|
-
# worktree 内也写入并提交——bash cd 不跨工具调用持久化,
|
|
279
|
-
# 若只在 source repo 写,agent 后续进入 worktree 后读到的 state 仍为 null
|
|
280
|
-
cd "$WT_PATH" && \
|
|
281
|
-
alloy _state write openspec/changes/<name> worktree "$WT_PATH" && \
|
|
282
|
-
alloy _state write openspec/changes/<name> worktree_branch "$WORKTREE_BRANCH" && \
|
|
283
|
-
alloy _state write openspec/changes/<name> worktree_created_at "$(date '+%Y-%m-%d %H:%M:%S')" && \
|
|
284
|
-
git add openspec/changes/<name>/.alloy.yaml && \
|
|
285
|
-
git diff --cached --quiet || git commit -m "chore(<name>): record worktree state (worktree)"
|
|
286
|
-
else
|
|
287
|
-
echo " ℹ 未检测到 worktree,按用户选择记录"
|
|
288
|
-
alloy _state write openspec/changes/<name> worktree skipped
|
|
289
|
-
fi
|
|
290
|
-
fi
|
|
291
|
-
|
|
292
|
-
技能执行完成后,将结果写入状态文件——这是断点恢复的关键数据(已在上方检测逻辑中自动写入):
|
|
293
|
-
- 已创建 worktree → worktree 路径(已在检测中自动写入到 state)
|
|
294
|
-
- 用户拒绝或已在隔离环境 → `skipped`(已在检测中自动写入到 state)
|
|
295
|
-
|
|
296
|
-
**Step 1/5 完成汇总:**
|
|
297
|
-
|
|
298
|
-
```
|
|
299
|
-
> [Step 1/5] 隔离环境 — 已跳过(用户选择不创建)
|
|
300
|
-
|
|
301
|
-
或
|
|
302
|
-
|
|
303
|
-
> [Step 1/5] 隔离环境 — 就绪
|
|
304
|
-
>
|
|
305
|
-
> 源分支: <由 state.feature_branch 获取>
|
|
306
|
-
> Worktree 分支: <由 state.worktree_branch 获取,无则显示 N/A>
|
|
307
|
-
> Worktree 路径: <由 state.worktree 获取,无则显示 N/A>
|
|
185
|
+
**Step 1/5 完成:**
|
|
186
|
+
```
|
|
187
|
+
> [Step 1/5] 隔离环境 — 已跳过 / 就绪
|
|
188
|
+
> 源分支: <feature_branch> Worktree: <path>/<branch> 或 N/A
|
|
189
|
+
> 分支锁: HEAD == worktree-<name> ✓
|
|
308
190
|
```
|
|
309
191
|
|
|
310
192
|
### [Step 2/5] 任务实现
|
|
311
193
|
|
|
312
|
-
**幂等检查:** 读取 `tasks.md`,扫描 checkbox 状态:
|
|
313
|
-
|
|
314
194
|
```
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
→ 从第一个未勾选的 task 开始执行
|
|
318
|
-
tasks.md: 7/7 已勾选 → ✓ 已完成,跳过此步骤
|
|
195
|
+
[HARD_STOP] TDD 次序不可颠倒——RED → GREEN → REFACTOR
|
|
196
|
+
违反字面 = 违反精神:哪怕"只改一行 case 没必要先写测试",也算违反 Iron Law 第一层
|
|
319
197
|
```
|
|
320
198
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
> 按 plans.md 微步骤执行实现...
|
|
199
|
+
**幂等检查:** 读取 `tasks.md` checkbox 状态。已勾选任务 TDD 测试仍通过,自然跳过;从第一个未勾选开始。
|
|
324
200
|
|
|
325
201
|
**先分析,再展示推荐方案:**
|
|
326
202
|
|
|
327
|
-
1. 读取 `plans.md` 的
|
|
328
|
-
2. 读取 `tasks.md
|
|
329
|
-
3.
|
|
203
|
+
1. 读取 `plans.md` frontmatter 的 `strategy` + `reason`
|
|
204
|
+
2. 读取 `tasks.md`,分析任务特征(数量、独立性、耦合度)
|
|
205
|
+
3. 展示推荐方案,用户可覆写:
|
|
206
|
+
- **subagent-driven-development** — 任务多(≥3)、相互独立、涉及不同文件/模块
|
|
207
|
+
- **executing-plans** — 任务少(1-2)、紧密耦合、共享状态
|
|
330
208
|
|
|
331
|
-
|
|
332
|
-
[Step 2/5] 执行策略选择
|
|
333
|
-
──────────────────────────────────────
|
|
334
|
-
|
|
335
|
-
任务分析:<N 个任务,哪些独立/哪些耦合>
|
|
336
|
-
|
|
337
|
-
推荐方案:superpowers:subagent-driven-development(规划阶段建议)
|
|
338
|
-
理由:<来自 plans.md reason>
|
|
339
|
-
|
|
340
|
-
选择哪个?
|
|
341
|
-
|
|
342
|
-
subagent-driven-development(推荐)
|
|
343
|
-
适用场景:
|
|
344
|
-
- 任务多(≥3 个)、相互独立
|
|
345
|
-
- 涉及不同文件/模块,可并行
|
|
346
|
-
- 适合:新功能、多组件改造、跨模块变更
|
|
347
|
-
|
|
348
|
-
executing-plans
|
|
349
|
-
适用场景:
|
|
350
|
-
- 任务少(1-2 个)、紧密耦合
|
|
351
|
-
- 共享状态或同一文件、不可拆分
|
|
352
|
-
- 适合:小修小改、重构单个模块、快速修复
|
|
353
|
-
```
|
|
209
|
+
plans.md 无 strategy 时分析后给出推荐(不标记),策略决定后回写 frontmatter 并重新 hash 锁定。
|
|
354
210
|
|
|
355
|
-
|
|
356
|
-
- 对应选项标记为"(推荐)"
|
|
357
|
-
- 用户不明确选择时,默认采用推荐方案
|
|
358
|
-
- 展示推荐时,一起展示 writing-plans 给出的 `reason`(策略背后的分析理由)
|
|
211
|
+
4. 🔴 USER_GATE(必须 AskUserQuestion): 选择执行策略(SDD / EP)。必须等用户选择后才加载技能。
|
|
359
212
|
|
|
360
|
-
|
|
361
|
-
- 分析任务特征后给出推荐
|
|
362
|
-
- 两个选项不标记推荐,等用户明确选择
|
|
363
|
-
- **策略决定后,将 strategy 回写到 plans.md YAML frontmatter**,补充 `strategy` 和 `reason` 字段,然后重新 hash 锁定。这确保后续 apply(如断线重连)不会重复分析。
|
|
213
|
+
**SDD 路径:**
|
|
364
214
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
4. 用户选择后,加载对应技能,**按其内部指引执行**,alloy 不重复建造选择闸门
|
|
368
|
-
|
|
369
|
-
Superpowers 技能内部行为(alloy 仅编排,不替代):
|
|
370
|
-
|
|
371
|
-
**superpowers:subagent-driven-development 路径:** 加载 `superpowers:subagent-driven-development` 技能,由其内部驱动:
|
|
372
|
-
- 读取 plan → 分派子 agent → 每个子 agent 独立执行 TDD + code review(transitive 激活)
|
|
373
|
-
- 子 agent 各自勾选 tasks.md 中对应任务的 checkbox
|
|
374
|
-
|
|
375
|
-
**技能加载后立即记录:**
|
|
215
|
+
**先记录技能使用,再加载技能:**
|
|
376
216
|
```bash
|
|
377
217
|
alloy _skill log openspec/changes/<name> apply superpowers:subagent-driven-development
|
|
378
218
|
alloy _skill log openspec/changes/<name> apply test-driven-development --via subagent-driven-development
|
|
@@ -380,192 +220,179 @@ alloy _skill log openspec/changes/<name> apply spec-compliance-review --via suba
|
|
|
380
220
|
alloy _skill log openspec/changes/<name> apply code-quality-review --via subagent-driven-development
|
|
381
221
|
```
|
|
382
222
|
|
|
383
|
-
|
|
223
|
+
加载 `superpowers:subagent-driven-development`,由其驱动分派子 agent → 每个独立 TDD + code review(transitive 激活)。
|
|
384
224
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
- 不在 executing-plans 内部"顺便做"——先设定预期,再执行
|
|
225
|
+
**构造子 agent 任务描述时,必须注入以下指令到任务描述末尾:**
|
|
226
|
+
> 实现完成时,在**同一个 commit** 中包含:实现代码 + 测试 + `openspec/changes/<name>/tasks.md` 中你负责的 task checkbox 从 `- [ ]` 改为 `- [x]`(含父级和子级)。不要分两个 commit。
|
|
388
227
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
228
|
+
**EP 路径:** 四步显式加载补偿(EP 不 transitive 激活 TDD/spec 合规/code review):
|
|
229
|
+
1. 加载 `test-driven-development`(设定 TDD 预期,RED→GREEN→REFACTOR 成为硬约束)
|
|
230
|
+
2. 加载 `executing-plans`(逐步执行 plans.md,每步遵循 TDD)
|
|
231
|
+
3. Spec 合规审查(Agent 自检:每个 checkbox ↔ 代码实现,无 over-building,排除范围未碰,不通过→修复→重审)
|
|
232
|
+
4. 加载 `requesting-code-review`(代码审查闸门——所有代码变更必须经审查才进 Step 3)
|
|
393
233
|
|
|
394
|
-
**2. 加载 `superpowers:executing-plans` 技能执行 plans.md 微步骤:**
|
|
395
|
-
- executing-plans 按 plans.md 逐步执行,每步完成后暂停审查
|
|
396
|
-
- 执行过程中遵循 TDD 流程(先写测试→确认失败→实现→确认通过)
|
|
397
|
-
|
|
398
|
-
**技能加载后立即记录:**
|
|
399
234
|
```bash
|
|
235
|
+
alloy _skill log openspec/changes/<name> apply superpowers:test-driven-development
|
|
400
236
|
alloy _skill log openspec/changes/<name> apply superpowers:executing-plans
|
|
237
|
+
alloy _skill log openspec/changes/<name> apply superpowers:requesting-code-review
|
|
401
238
|
```
|
|
402
239
|
|
|
403
|
-
|
|
404
|
-
- tasks.md 的每个 checkbox → 代码中是否有对应实现?
|
|
405
|
-
- 代码中是否有 tasks.md 未要求的实现?(over-building)
|
|
406
|
-
- plan.md 中明确排除的范围 → 代码是否碰了?
|
|
407
|
-
- 不通过 → 修复 → 重新审查 → 通过后进入 code review
|
|
240
|
+
---
|
|
408
241
|
|
|
409
|
-
|
|
410
|
-
- 代码审查闸门——所有代码变更必须经过审查才能进入 Step 3 验证
|
|
242
|
+
#### Step 2/5 子 agent commit 通用规则(SDD/EP 共享)
|
|
411
243
|
|
|
412
|
-
|
|
413
|
-
```bash
|
|
414
|
-
alloy _skill log openspec/changes/<name> apply superpowers:requesting-code-review
|
|
415
|
-
```
|
|
244
|
+
每个子 agent 任务的 commit 必须满足以下三条硬规则——任一违反即拒绝合入。读取 `commands/alloy/references/apply-subagent-commit.md` 获取完整 bash 与措辞,要点:
|
|
416
245
|
|
|
417
|
-
|
|
246
|
+
1. **分支再校验**(⛔ PRECONDITION_FAIL,task #18)—— `git rev-parse --abbrev-ref HEAD` ≠ `worktree-<name>` 时退出,禁 agent 自动 `git checkout` 切回。
|
|
247
|
+
2. **git add 限路径**(⛔ HARD_STOP §5.2.1)—— 精确路径,禁 `-A`/`-a`/`.`。违反字面 = 违反精神:哪怕"反正只有这一个文件"也禁 `-A`,副作用文件会被一并 commit。判断不准 🔴 USER_GATE。
|
|
248
|
+
3. **stash 残留检查**(⚠️ WARN,task #19)—— commit 前 `git stash list`,非空播报让用户决策,禁 agent 自动 `git stash drop`(§3.5.1)。
|
|
418
249
|
|
|
419
250
|
### [Step 3/5] 代码层验证
|
|
420
251
|
|
|
421
|
-
|
|
422
|
-
> 正在验证代码行为——测试通过、功能正确...
|
|
252
|
+
加载 `superpowers:verification-before-completion` 技能——代码行为验证。
|
|
423
253
|
|
|
424
|
-
使用 Skill 工具加载 `superpowers:verification-before-completion` 技能 —— 代码行为验证。
|
|
425
|
-
|
|
426
|
-
**技能加载后立即记录:**
|
|
427
254
|
```bash
|
|
428
255
|
alloy _skill log openspec/changes/<name> apply superpowers:verification-before-completion
|
|
429
256
|
```
|
|
430
257
|
|
|
431
|
-
|
|
258
|
+
**验证失败处理(⛔ HARD_STOP):**
|
|
259
|
+
|
|
260
|
+
> ⛔ [HARD_STOP] verify-before-completion FAIL → 修复代码回到 Step 2,修复也必须 TDD + code review。
|
|
261
|
+
> 禁止:agent 在 retrospective 中标记"已知 FAIL 跳过修复"——FAIL 必须修到 PASS 才能进 Step 4。
|
|
262
|
+
> 违反字面 = 违反精神:哪怕"小问题先记 deferred 跳过",也算违反 Iron Law——
|
|
263
|
+
> 带 FAIL 进 archive = spec 与代码偏差永久封存。
|
|
432
264
|
|
|
433
265
|
### [Step 4/5] 制品层验证
|
|
434
266
|
|
|
435
|
-
**幂等检查:**
|
|
267
|
+
**幂等检查:**
|
|
436
268
|
```bash
|
|
437
269
|
alloy _record check openspec/changes/<name> verify 2>/dev/null && echo "VERIFY_DONE" || echo "VERIFY_NEEDED"
|
|
438
270
|
```
|
|
271
|
+
VERIFY_DONE → 跳过 Step 4。
|
|
439
272
|
|
|
440
|
-
|
|
441
|
-
Step 4/5 进度检测:
|
|
442
|
-
verify.md 存在 + hash 有效 → ✓ 已完成,跳过此步骤
|
|
443
|
-
verify.md 缺失或 hash 无效 → 执行制品验证
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
verify.md 已完成时,跳过 Step 4,直接进入 Step 5。
|
|
447
|
-
|
|
448
|
-
> [Step 4/5] 制品层验证
|
|
449
|
-
> 正在验证制品结构——7 项结构化检查 → verify.md...
|
|
273
|
+
**生成 verify 前,校验 plans 上游 hash(⛔ PRECONDITION_FAIL):**
|
|
450
274
|
|
|
451
|
-
**生成 verify 前,校验上游 plans 的 hash:**
|
|
452
275
|
```bash
|
|
453
276
|
alloy _record check openspec/changes/<name> plans
|
|
454
277
|
```
|
|
455
|
-
若 check 失败 → HARD STOP,plans 可能被未审批修改。
|
|
456
278
|
|
|
457
|
-
|
|
279
|
+
check 失败 → ⛔ `[PRECONDITION_FAIL] plans 上游 hash 失效——plans.md 可能被未审批修改`。修复路径:用户审查 plans.md 变更后,决定是否回到 plan 阶段重新锁定,或回滚 plans.md 到锁定版本。**禁止 agent 自动 `alloy _record write` 重新锁定——绕过审查 = 绕过 hash chain(§5.2.3)。**
|
|
458
280
|
|
|
459
|
-
|
|
460
|
-
```bash
|
|
461
|
-
alloy _skill log openspec/changes/<name> apply opsx:verify
|
|
462
|
-
```
|
|
463
|
-
2.
|
|
464
|
-
3. 检查结果(PASS/FAIL/WARNING)保留作为事实依据
|
|
281
|
+
1. 调用 `/opsx:verify` 执行 7 项检查(结构校验 → 任务完成 → Delta Spec 同步 → Design/Specs 一致性 → 实现信号 → 路由泄漏检测 → 延期任务对照)
|
|
282
|
+
```bash
|
|
283
|
+
alloy _skill log openspec/changes/<name> apply opsx:verify
|
|
284
|
+
```
|
|
285
|
+
2. 输出必须重写为与 `instructions/verify.md` 和 `templates/verify.md` 一致的语言,不直接透传 CLI 输出。检查结果(PASS/FAIL/WARNING)保留作为事实依据。
|
|
465
286
|
|
|
466
|
-
|
|
287
|
+
**opsx:verify 失败处理(⛔ HARD_STOP):**
|
|
467
288
|
|
|
468
|
-
|
|
289
|
+
> ⛔ [HARD_STOP] opsx:verify 7 项有 FAIL → 修复 → 回到 Step 2(SDD),禁带 FAIL 继续 Step 5。
|
|
290
|
+
> 违反字面 = 违反精神:哪怕"FAIL 仅 1 项 retro 写一笔继续",也算违反——FAIL 必须先修到 PASS。
|
|
291
|
+
> WARNING 项可继续,但需在 retrospective §2 Misses 记录。
|
|
469
292
|
|
|
470
|
-
**tasks.md checkbox 已更新,重录 hash
|
|
293
|
+
**tasks.md checkbox 已更新,重录 hash(§5.2.1 git add 限路径):**
|
|
471
294
|
```bash
|
|
472
295
|
HASH=$(alloy _record compute openspec/changes/<name> tasks)
|
|
473
296
|
alloy _record write openspec/changes/<name> tasks "$HASH" "$(date "+%Y-%m-%d %H:%M:%S")" "$(alloy _record approver openspec/changes/<name>)"
|
|
474
297
|
```
|
|
475
298
|
|
|
476
|
-
**verify.md
|
|
299
|
+
**verify.md 审查窗口(🔴 USER_GATE):**
|
|
477
300
|
|
|
478
|
-
> 制品 [1/2] verify ✓
|
|
479
|
-
>
|
|
301
|
+
> 制品 [1/2] verify ✓ 完成
|
|
480
302
|
> [展示 verify.md 完整内容]
|
|
303
|
+
> 🔴 USER_GATE(必须 AskUserQuestion): 确认锁定 verify
|
|
304
|
+
> (a) 确认并继续——hash-lock + commit
|
|
305
|
+
> (b) 需要调整——重新生成 verify.md(禁直接编辑),重展示审查窗口
|
|
481
306
|
>
|
|
482
|
-
>
|
|
483
|
-
>
|
|
484
|
-
> → (b) 需要调整 — 说明修改点,修改后重新展示
|
|
307
|
+
> 违反字面 = 违反精神:哪怕 verify.md 看似"明显合理",没经过用户明确选择 (a) = 不算授权。
|
|
308
|
+
> 禁止 agent 基于"diff 短"或"全 PASS"自动跳过此 USER_GATE,必须完整阅读 diff。
|
|
485
309
|
|
|
486
|
-
选 (a):hash 锁定
|
|
310
|
+
选 (a):hash 锁定 + commit(§5.2.1 git add 限路径):
|
|
487
311
|
```bash
|
|
488
312
|
HASH=$(alloy _record compute openspec/changes/<name> verify)
|
|
489
313
|
APPROVED_AT=$(date "+%Y-%m-%d %H:%M:%S")
|
|
490
314
|
APPROVER=$(alloy _record approver openspec/changes/<name>)
|
|
491
315
|
alloy _record write openspec/changes/<name> verify "$HASH" "$APPROVED_AT" "$APPROVER"
|
|
492
|
-
|
|
316
|
+
# §5.2.1: 限路径,禁 -A
|
|
317
|
+
git add openspec/changes/<name>/verify.md openspec/changes/<name>/.alloy.yaml
|
|
493
318
|
git commit -m "docs(<name>): verify 已确认"
|
|
494
319
|
```
|
|
495
320
|
|
|
496
|
-
选 (b)
|
|
321
|
+
选 (b):重新生成 verify.md(不是直接编辑),重新展示审查窗口。
|
|
322
|
+
|
|
323
|
+
> [N/M] 是阶段内局部编号(M=2),不输出全局制品进度。全局进度由 `alloy status` 管理。
|
|
497
324
|
|
|
498
325
|
### [Step 5/5] 复盘
|
|
499
326
|
|
|
500
|
-
**幂等检查:**
|
|
327
|
+
**幂等检查:**
|
|
501
328
|
```bash
|
|
502
329
|
alloy _record check openspec/changes/<name> retrospective 2>/dev/null && echo "RETRO_DONE" || echo "RETRO_NEEDED"
|
|
503
330
|
```
|
|
331
|
+
RETRO_DONE → 跳过 Step 5。
|
|
504
332
|
|
|
333
|
+
**PRECHECK:** verify.md 通过检查(⛔ PRECONDITION_FAIL):
|
|
334
|
+
```bash
|
|
335
|
+
alloy _guard verify-passed openspec/changes/<name>
|
|
505
336
|
```
|
|
506
|
-
Step
|
|
507
|
-
retrospective.md 存在 + hash 有效 → ✓ 已完成,跳过此步骤
|
|
508
|
-
retrospective.md 缺失或 hash 无效 → 执行复盘
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
retrospective.md 已完成时,跳过 Step 5,直接进入完成阶段。
|
|
512
|
-
|
|
513
|
-
> [Step 5/5] retrospective
|
|
514
|
-
> 正在生成全周期复盘报告(§0-§6)...
|
|
515
|
-
|
|
516
|
-
读取 `instructions/retrospective.md`,按模板 `templates/retrospective.md` 生成 `openspec/changes/<name>/retrospective.md`。
|
|
337
|
+
FAIL → ⛔ `[PRECONDITION_FAIL] verify.md 未通过——retrospective 不得在 FAIL 状态下生成`。修复路径:回到 Step 3/Step 4 修复后重锁 verify。PASS/WARNING → 继续。
|
|
517
338
|
|
|
518
|
-
|
|
339
|
+
**校验 verify 上游 hash(⛔ PRECONDITION_FAIL):**
|
|
519
340
|
|
|
520
|
-
**生成 retrospective 前,校验上游 verify 的 hash:**
|
|
521
341
|
```bash
|
|
522
342
|
alloy _record check openspec/changes/<name> verify
|
|
523
343
|
```
|
|
524
|
-
若 check 失败 → HARD STOP。
|
|
525
344
|
|
|
526
|
-
|
|
345
|
+
失败 → ⛔ `[PRECONDITION_FAIL] verify 上游 hash 失效——verify.md 可能被未审批修改`。禁止 agent 自动重新锁定,必须用户审查后决定。
|
|
527
346
|
|
|
528
|
-
|
|
347
|
+
读取 `instructions/retrospective.md`,按 `templates/retrospective.md` 生成。输出语言与模板一致。代码标识符、commit hash、文件名保持原文。
|
|
529
348
|
|
|
530
|
-
**§1 Wins
|
|
349
|
+
**§0-§6:** §0 量化全景(records + git log + 文件系统三来源)、§1 Wins(evidence 格式)、§2 Misses(🔴 blocking / 🟡 painful / 📌 nit)、§3 Plan Deviations、§4 技能审计(从 `.alloy.yaml` skill_usage[] 读取,空填 `—`,跳过的展开三问)、§5 Surprises、§6 Promote Candidates(`→ Promote to: memory` 的条目在 archive 阶段写入 memory)。
|
|
531
350
|
|
|
532
|
-
|
|
351
|
+
**Retrospective 跳过判定(🔴 USER_GATE + ⛔ HARD_STOP,task #17):**
|
|
533
352
|
|
|
534
|
-
|
|
353
|
+
复盘是证据驱动的——每条结论引用具体 commit 或文件。判定流程:
|
|
535
354
|
|
|
536
|
-
|
|
355
|
+
```bash
|
|
356
|
+
FEATURE_BRANCH=$(alloy _state read openspec/changes/<name> feature_branch 2>/dev/null)
|
|
357
|
+
COMMIT_COUNT=$(git log "${FEATURE_BRANCH}..HEAD" --oneline 2>/dev/null | wc -l | tr -d ' ')
|
|
358
|
+
echo "本 change 累计 commit 数: $COMMIT_COUNT"
|
|
359
|
+
```
|
|
537
360
|
|
|
538
|
-
|
|
361
|
+
- `COMMIT_COUNT == 1` 时:可能符合"单 commit 小修跳过"条件,但 **🔴 USER_GATE(必须 AskUserQuestion,不得 agent 自动选):**
|
|
539
362
|
|
|
540
|
-
|
|
363
|
+
> 本 change 仅 1 个 commit,是否跳过 retrospective?
|
|
364
|
+
> (a) 不跳过——正常生成(推荐:即使小改也常有可记录的洞察)
|
|
365
|
+
> (b) 跳过——写入 retrospective.md 仅含 "Skipped: single-commit fix, no insights"
|
|
366
|
+
>
|
|
367
|
+
> [HARD_STOP] agent 不得自动选 (b)。即使 COMMIT_COUNT == 1,跳过也必须用户明确选择 (b)。
|
|
368
|
+
> 违反字面 = 违反精神:哪怕"用户上次也选了跳过所以这次猜跳过",也是违反——每次必须 ask。
|
|
541
369
|
|
|
542
|
-
|
|
543
|
-
跳过策略:单 commit 小修可跳过,写 "Skipped: single-commit fix, no insights"。
|
|
370
|
+
- `COMMIT_COUNT > 1`:直接生成 retrospective,不询问跳过。
|
|
544
371
|
|
|
545
|
-
**retrospective.md
|
|
372
|
+
**retrospective.md 审查窗口(🔴 USER_GATE):**
|
|
546
373
|
|
|
547
374
|
> 制品 [2/2] retrospective ✓ 完成
|
|
548
|
-
>
|
|
549
375
|
> [展示 retrospective.md 完整内容]
|
|
376
|
+
> 🔴 USER_GATE(必须 AskUserQuestion): 确认锁定 retrospective
|
|
377
|
+
> (a) 确认并继续提交
|
|
378
|
+
> (b) 需要调整——重新生成(禁直接编辑),重展示审查窗口
|
|
550
379
|
>
|
|
551
|
-
>
|
|
552
|
-
> → (a) 确认,锁定 retrospective 并完成 apply
|
|
553
|
-
> → (b) 需要调整 — 说明修改点,修改后重新展示
|
|
380
|
+
> 违反字面 = 违反精神:禁 agent 基于"内容看起来挺全"自动跳过此 USER_GATE。
|
|
554
381
|
|
|
555
|
-
选 (a)
|
|
382
|
+
选 (a):审批时间 + hash 锁定 + commit(一个 commit 包含所有累积变更——retrospective + 阶段完成时间 + worktree 状态)(§5.2.1 git add 限路径):
|
|
556
383
|
```bash
|
|
557
384
|
APPROVAL_TIME=$(date "+%Y-%m-%d %H:%M:%S")
|
|
558
|
-
# 将 §0 表格中 retrospective 行的"待确认"替换为实际审批时间(hash 列保持 "—",避免自指悖论)
|
|
559
385
|
sed -i '' "s/| retrospective |.*| 待确认 |/| retrospective | $(alloy _record approver openspec/changes/<name>) | — | ${APPROVAL_TIME} |/" openspec/changes/<name>/retrospective.md
|
|
560
386
|
COMPLETED_AT="${APPROVAL_TIME}"
|
|
561
387
|
alloy _state merge openspec/changes/<name> phase_timings "{\"apply\":{\"completed_at\":\"${COMPLETED_AT:-$(date '+%Y-%m-%d %H:%M:%S')}\"}}"
|
|
562
388
|
HASH=$(alloy _record compute openspec/changes/<name> retrospective)
|
|
563
389
|
alloy _record write openspec/changes/<name> retrospective "$HASH" "$APPROVAL_TIME" "$(alloy _record approver openspec/changes/<name>)"
|
|
390
|
+
# §5.2.1: git add 限路径,禁 -A——openspec/changes/<name>/ 是该 change 的根目录,不会扩散
|
|
564
391
|
git add openspec/changes/<name>/
|
|
565
392
|
git commit -m "docs(<name>): retrospective 已确认"
|
|
566
393
|
```
|
|
567
394
|
|
|
568
|
-
选 (b)
|
|
395
|
+
选 (b):重新生成(不是直接编辑),重新展示审查窗口。
|
|
569
396
|
|
|
570
397
|
---
|
|
571
398
|
|
|
@@ -574,67 +401,32 @@ git commit -m "docs(<name>): retrospective 已确认"
|
|
|
574
401
|
```
|
|
575
402
|
┌──────────────────────────────────────┐
|
|
576
403
|
│ Alloy [3/5] · Phase: Apply — DONE │
|
|
577
|
-
│ 启动时间:
|
|
578
|
-
│ 完成时间:
|
|
579
|
-
│ 耗时: completed_at - started_at
|
|
404
|
+
│ 启动时间: phase_timings.apply.started_at
|
|
405
|
+
│ 完成时间: phase_timings.apply.completed_at
|
|
406
|
+
│ 耗时: completed_at - started_at
|
|
580
407
|
└──────────────────────────────────────┘
|
|
581
408
|
|
|
582
|
-
→ Change: <name>
|
|
583
|
-
→
|
|
584
|
-
→
|
|
585
|
-
|
|
586
|
-
所有制品已生成并锁定:
|
|
587
|
-
|
|
588
|
-
制品 状态 Hash 创建时间
|
|
589
|
-
────────────── ──── ──────────── ───────────────────
|
|
590
|
-
plans ✓ <hash> <timestamp>
|
|
591
|
-
verify ✓ <hash> <timestamp>
|
|
592
|
-
retrospective ✓ <hash> <timestamp>
|
|
593
|
-
|
|
594
|
-
→ 代码变更已提交
|
|
595
|
-
→ 验证: <PASS 或 存在 N 个 WARN>
|
|
409
|
+
→ Change: <name> Phase: applied Worktree: <path 或 当前分支>
|
|
410
|
+
→ 制品: plans ✓ verify ✓ retrospective ✓
|
|
411
|
+
→ 代码变更已提交 验证: <PASS 或 N 个 WARN>
|
|
596
412
|
```
|
|
597
413
|
|
|
598
|
-
**apply
|
|
599
|
-
- 代码变更:SDD 过程中每次成功验证后立即 commit
|
|
600
|
-
- verify.md / retrospective.md:用户通过审查窗口选 (a) 确认后,hash 锁定 + commit(具体命令已内联在上方各审查窗口中)
|
|
601
|
-
|
|
602
|
-
**SDD commit 前检查 untracked 文件:**
|
|
603
|
-
|
|
604
|
-
commit 实现代码前,先检查是否有未跟踪文件:
|
|
605
|
-
```bash
|
|
606
|
-
UNTRACKED=$(git status --porcelain | grep '^??' | sed 's/^?? //')
|
|
607
|
-
```
|
|
414
|
+
**apply 完成后不要自动进入 archive** — archive 是人工闸门,留给用户做 QA。
|
|
608
415
|
|
|
609
|
-
|
|
610
|
-
- **构建产物或临时文件**(`.vite/`、`dist/`、`build/`、`.next/`、`.cache/`、`*.log`、`node_modules/` 等)→ 追加到 `.gitignore`,`git add .gitignore` 一起提交
|
|
611
|
-
- **项目源码**(`.ts`、`.vue`、`.css` 等新创建的文件)→ 按精准路径 `git add`
|
|
416
|
+
**通过 `alloy _guard` 校验并推进 phase(⛔ HARD_STOP §5.2.3 路径 B 降级):**
|
|
612
417
|
|
|
613
|
-
|
|
418
|
+
降级路径详见 `commands/alloy/references/phase-downgrade-path.md`(apply 阶段降级 → `planned`)。**禁止 agent 自动 `git reset --hard` / `git checkout .` 清场(§3.5.1)。** 违反字面 = 违反精神:哪怕"清理一下让流程重启"也算违反——退出 skill 让用户决策是唯一合法路径。
|
|
614
419
|
|
|
615
|
-
**通过 `alloy _guard` 校验并更新 phase(必须在 worktree 中执行,若使用了 worktree):**
|
|
616
420
|
```bash
|
|
617
421
|
alloy _guard openspec/changes/<name> applied --apply
|
|
422
|
+
# §5.2.1 git add 限路径,禁 -A
|
|
618
423
|
git add openspec/changes/<name>/.alloy.yaml
|
|
619
424
|
git commit -m "chore(<name>): phase → applied"
|
|
620
425
|
```
|
|
621
|
-
guard 自动校验 hash 一致性后推进 phase。phase 变更必须 commit,否则 worktree 清理时未提交的变更会丢失。
|
|
622
426
|
|
|
623
|
-
|
|
624
|
-
💡 建议:可以执行 QA 测试或浏览器测试等质量检查,确认后再进入 archive。
|
|
427
|
+
`git commit` 失败 → ⛔ `[HARD_STOP] phase commit 失败,apply 中止。.alloy.yaml 变更未提交时 archive 状态不一致。检查 git 状态后重试,禁止在 commit 失败时继续。`
|
|
625
428
|
|
|
626
|
-
准备好后,运行 `/alloy:archive` 进入归档阶段。
|
|
627
429
|
```
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
## 闸门规则
|
|
632
|
-
|
|
633
|
-
- **git add 只用精确路径** — 永远不用 `-A`、`-a`、`.`。
|
|
634
|
-
代码变更只 add 本次改动的具体文件;反例:`git add .` 会把第三方依赖、临时文件一起提交
|
|
635
|
-
- **precheck 不过不执行** —— 6 个技能任一缺失即 STOP,不静默降级
|
|
636
|
-
- **verify 不通过不结束 apply** —— 两层验证(代码层 + 制品层),任意 FAIL 回到 SDD
|
|
637
|
-
- **retrospective PRECHECK** —— verify.md 不存在或 Overall Decision 是 FAIL 时 STOP
|
|
638
|
-
- **apply 完成后不要自动进入 archive** —— archive 是人工闸门,留给用户空间做 QA
|
|
639
|
-
- **每制品独立 commit** — verify 和 retrospective 单独 hash 锁定并 commit
|
|
640
|
-
- **不输出全局制品进度** — [N/M] 是阶段内局部编号(M=2),不要输出"N/8 artifacts 完成"。全局进度由 `alloy status` 管理
|
|
430
|
+
💡 建议执行 QA 测试或浏览器测试,确认后再进入 archive。
|
|
431
|
+
准备好后,运行 /alloy:archive 进入归档阶段。
|
|
432
|
+
```
|