@flyin-ai/alloy 0.2.0-beta.0 → 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.
Files changed (41) hide show
  1. package/commands/alloy/apply.md +222 -430
  2. package/commands/alloy/archive.md +156 -132
  3. package/commands/alloy/discard.md +26 -11
  4. package/commands/alloy/finish.md +212 -116
  5. package/commands/alloy/fix.md +103 -258
  6. package/commands/alloy/plan.md +204 -301
  7. package/commands/alloy/references/apply-precheck.md +21 -0
  8. package/commands/alloy/references/apply-rationalizations.md +18 -0
  9. package/commands/alloy/references/apply-subagent-commit.md +49 -0
  10. package/commands/alloy/references/apply-worktree.md +130 -0
  11. package/commands/alloy/references/archive-rationalizations.md +16 -0
  12. package/commands/alloy/references/archive-worktree-cleanup.md +94 -0
  13. package/commands/alloy/references/artifact-hash-commit.md +49 -0
  14. package/commands/alloy/references/branch-naming.md +65 -0
  15. package/commands/alloy/references/branch-validation.md +36 -0
  16. package/commands/alloy/references/fix-precommit-check.md +58 -0
  17. package/commands/alloy/references/interaction-style.md +34 -1
  18. package/commands/alloy/references/main-branch-detection.md +3 -6
  19. package/commands/alloy/references/phase-downgrade-path.md +27 -0
  20. package/commands/alloy/references/plan-rollback.md +84 -0
  21. package/commands/alloy/references/spec-sync.md +62 -0
  22. package/commands/alloy/references/start-rationalizations.md +18 -0
  23. package/commands/alloy/start.md +189 -227
  24. package/dist/cli/commands/completion.js +13 -2
  25. package/dist/cli/commands/completion.js.map +1 -1
  26. package/dist/cli/commands/internal/artifact.d.ts +7 -0
  27. package/dist/cli/commands/internal/artifact.js +70 -0
  28. package/dist/cli/commands/internal/artifact.js.map +1 -0
  29. package/dist/cli/commands/internal/guard.js +204 -2
  30. package/dist/cli/commands/internal/guard.js.map +1 -1
  31. package/dist/cli/commands/internal/progress.d.ts +10 -0
  32. package/dist/cli/commands/internal/progress.js +70 -0
  33. package/dist/cli/commands/internal/progress.js.map +1 -0
  34. package/dist/cli/commands/internal/spec-audit.d.ts +42 -0
  35. package/dist/cli/commands/internal/spec-audit.js +363 -0
  36. package/dist/cli/commands/internal/spec-audit.js.map +1 -0
  37. package/dist/cli/commands/internal/state.js +4 -0
  38. package/dist/cli/commands/internal/state.js.map +1 -1
  39. package/dist/cli/index.js +30 -0
  40. package/dist/cli/index.js.map +1 -1
  41. package/package.json +2 -1
@@ -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 的执行阶段编排器。按 plan.md 任务实现,内部遵循 TDD,执行完毕自动验证和复盘。
19
+ 你是 Alloy 的执行阶段编排器。按 plans.md 任务实现,内部遵循 TDD,执行完毕自动验证和复盘。
11
20
 
12
- **交互风格:** 所有审查窗口、分支选择、策略选择使用 `AskUserQuestion` 工具。详见 `commands/alloy/references/interaction-style.md`。
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
- **什么算"apply 执行不到位"(反例):**
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
- ### Red Flags——STOP,不要继续
34
-
35
- 以下任何一个念头出现,都意味着闸门正在被绕过:
44
+ 主文件保留 5 条核心借口,完整 12 条见 `commands/alloy/references/apply-rationalizations.md`。
36
45
 
37
46
  | 借口 | 现实 |
38
47
  |------|------|
39
- | "用户说了跳过 worktree" | 用户说了不算。隔离是 apply 的硬闸门,用户跳过 worktree 就是跳过安全网。必须明确拒绝并解释风险。 |
40
- | "先写代码再补测试,加快速度" | TDD 的次序不可颠倒。先写测试再写代码才是安全网,顺序反了等于没网。提速的正确方式是并行子任务,不是砍测试。 |
41
- | "用户要改需求,我直接改吧" | 需求变更必须通过 tasks.md checkbox 闸门。已开始编码 开新 change。未开始 回溯 brainstorming。不存在"顺手改了"这个选项。 |
42
- | "技能缺失没关系,我可以自己搞定" | 技能是闸门,不是加速器。缺失 = HARD STOP。不存在"降级处理"。引导 `alloy init` 修复环境。 |
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
- **提交前置状态(worktree 创建前确保 .alloy.yaml 变更已落地):**
78
- 后续步骤写入 worktree 的路径和分支名也会进入此快照 commit,确保 worktree 内能看到完整状态。
67
+ **2. phase 路由(PRECONDITION_FAIL):**
79
68
 
80
69
  ```bash
81
- git add openspec/changes/<name>/.alloy.yaml
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
- `git diff --cached --quiet` 接续时无变更则跳过,不会产生空 commit。
73
+ phase=planned applied 时通过(applied 为断点重入)。不匹配 → ⛔ `[PRECONDITION_FAIL]`,读取 `commands/alloy/references/phase-routing.md` 自动跳转。
86
74
 
87
- ---
75
+ **3. git 仓库(PRECONDITION_FAIL):**
88
76
 
89
- 前置检查通过:plan.md ✓ phase=planned ✓ git ✓ 技能 ✓
77
+ ```bash
78
+ git rev-parse --git-dir
79
+ ```
90
80
 
91
- > 共 5 个步骤:隔离 任务实现 代码验证 制品验证 复盘
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
- ## 需求变更处理(Apply 阶段回溯闸门)
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
- **检查 tasks.md checkbox 状态:**
91
+ 提交前置状态(worktree 创建前确保 .alloy.yaml 变更已落地):
102
92
  ```bash
103
- grep -c '\[x\]' openspec/changes/<name>/tasks.md
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
- - 返回 0(全部 unchecked)→ 尚未开始编码,允许回溯
107
- - 返回 > 0(有已勾选任务)→ 编码已开始,拒绝回溯
98
+ 前置检查通过:plans.md ✓ phase ✓ git ✓ 技能
108
99
 
109
- **未开始编码(全部 unchecked):**
100
+ > 共 5 步:隔离 → 任务实现 → 代码验证 → 制品验证 → 复盘
110
101
 
111
- > → (a) 确认变更,回到 brainstorming(清理 plan 制品,在当前 change 内修正)
112
- > → (b) 取消,继续 apply
102
+ ---
113
103
 
114
- 用户选 (a) → 执行 plan.md 的"回溯清理步骤"(删除 proposal/design/tasks/plans/specs,重置 records/phase_timings),回到 brainstorming。
104
+ ## 需求变更闸门
115
105
 
116
- **编码已开始(有 [x]):**
106
+ 用户提出需求/设计变更时,以编码是否已开始为分界线:
117
107
 
118
- > 编码已开始(<N> 个任务已完成),需求变更应开新 change:
119
- > /alloy:start <建议名称>
120
- >
121
- > 当前 change 继续执行,或 /alloy:discard 放弃。
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
- 不允许在当前 change 内回溯——已有代码落地,规格和代码不能分叉。
119
+ - **返回 > 0(已编码):** 🔴 USER_GATE(必须 AskUserQuestion): 检测到需求变更,tasks 已有编码完成项。选择处理路径:
120
+ - (a) 开新 change 处理变更(引导 `/alloy:start <建议名称>`)
121
+ - (b) 取消变更,继续 apply
124
122
 
125
- **什么算"需求变更闸门失效"(反例):**
126
- - 用户说"需求不对,改一下"就直接改代码——没检查 tasks.md checkbox 状态
127
- - 已在 [x] 的 change 上做架构级改动(如 JWT→session)——应开新 change
128
- - 用户说"就改一点点需求"——不存在"一点点",要么未编码可回溯,要么已编码开新 change
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
- **幂等检查:** 先读取 worktree 状态:
136
- ```bash
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
- Step 1/5 进度检测:
142
- worktree 值: 有效路径(如 `.claude/worktrees/<name>/` 或 `.worktrees/<name>/`)→ 路径存在 → ✓ 已完成,跳过此步骤
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
- 路径存在、"skipped" 时,直接跳过 Step 1,进入 Step 2。
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
- null 时,先展示摘要,再加载技能:
145
+ **分支验证闸门(PRECONDITION_FAIL)**——加载 using-git-worktrees 前必须通过;base ref 取决于当前分支,错误 base = plan 阶段 commit 丢失:
151
146
 
152
- ```
153
- > [Step 1/5] 隔离环境设置
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
- **分支验证闸门**(加载 using-git-worktrees 之前必须通过——worktree base ref 取决于当前分支,错误的 base = plan 阶段 commit 丢失):
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
- **① 主分支确认:** 读取 `commands/alloy/references/main-branch-detection.md`,按 3 级优先级检测主分支。若 `openspec/config.yaml` 已有 `alloy.main_branch` 记录,直接用记录值,跳过检测和确认。
157
+ 详细分类与修复选项见 `commands/alloy/references/branch-validation.md`。**禁止 agent 自动 `git checkout` 切换或 `git branch -m` 重命名——可能丢弃用户未提交工作(§3.5.1)。**
169
158
 
170
- **② 当前分支位置检查:**
171
- ```bash
172
- CURRENT_BRANCH=$(git branch --show-current)
173
- FEATURE_BRANCH=$(alloy _state read openspec/changes/<name> feature_branch)
174
- MAIN_BRANCH=$(alloy _config read . main_branch 2>/dev/null || echo "$DEFAULT_BRANCH")
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 _state write openspec/changes/<name> worktree skipped
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
- **用户选择创建:** 使用以下方式确保正确的 base ref(不是 origin/main,而是 feature_branch):
174
+ **用户选择不创建:** `alloy _state write openspec/changes/<name> worktree skipped`,跳到 Step 1 完成框。
233
175
 
234
- 1. **优先:** 先手动 `git worktree add .claude/worktrees/<name> -b worktree-<name> <feature_branch>` 创建 worktree(显式指定 base ref),再用 EnterWorktree(path=".claude/worktrees/<name>") 进入
235
- 2. **回退:** 若 EnterWorktree 支持自定义 base ref(查看工具参数),直接使用并传入 feature_branch
176
+ **用户选择创建:** 手动创建确保正确 base ref
236
177
 
237
- **路径偏好说明:** 使用无条件路径 `.claude/worktrees/<name>`,因为 `.claude/` alloy 初始化时的固定目录(存在 commands/skills 等子目录)。显式指定路径后,Agent 在 git worktree fallback(EnterWorktree 不可用时)会直接使用该路径,不会因条件判断错误而回退到 `.worktrees/`。
178
+ **路径占用检查 + 创建后状态记录 + worktree 内分支锁定**:读取 `commands/alloy/references/apply-worktree.md`:
238
179
 
239
- **分支命名说明:** 使用 `worktree-<name>` 命名规范,与 EnterWorktree 的内置命名一致。这确保无论 worktree EnterWorktree 还是 git worktree fallback 创建,分支名格式统一,archive 阶段清理时无需猜测。
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
- ```bash
242
- echo " 正在检测 worktree 实际状态..."
243
-
244
- # 判断是否已在 worktree 中:GIT_DIR != GIT_COMMON 表示在 linked worktree 中
245
- GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
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
- Step 2/5 进度检测:
316
- tasks.md: 3/7 已勾选 已完成的 task TDD 测试仍通过,自然跳过
317
- → 从第一个未勾选的 task 开始执行
318
- tasks.md: 7/7 已勾选 → ✓ 已完成,跳过此步骤
195
+ [HARD_STOP] TDD 次序不可颠倒——RED → GREEN → REFACTOR
196
+ 违反字面 = 违反精神:哪怕"只改一行 case 没必要先写测试",也算违反 Iron Law 第一层
319
197
  ```
320
198
 
321
- TDD 机制天然保证幂等——已实现的 task 对应测试已通过,重跑时自动跳过。无需额外检测。
322
-
323
- > 按 plans.md 微步骤执行实现...
199
+ **幂等检查:** 读取 `tasks.md` checkbox 状态。已勾选任务 TDD 测试仍通过,自然跳过;从第一个未勾选开始。
324
200
 
325
201
  **先分析,再展示推荐方案:**
326
202
 
327
- 1. 读取 `plans.md` 的 YAML frontmatter,提取 `strategy` `reason`
328
- 2. 读取 `tasks.md`,分析任务特征——任务数、独立性、耦合度、并行潜力
329
- 3. 展示推荐方案(来自 plans.md header),用户可覆写:
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
- **如果 plans.md strategy header:**
356
- - 对应选项标记为"(推荐)"
357
- - 用户不明确选择时,默认采用推荐方案
358
- - 展示推荐时,一起展示 writing-plans 给出的 `reason`(策略背后的分析理由)
211
+ 4. 🔴 USER_GATE(必须 AskUserQuestion): 选择执行策略(SDD / EP)。必须等用户选择后才加载技能。
359
212
 
360
- **如果 plans.md 无 strategy header(兼容旧 change):**
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
- **superpowers:executing-plans 路径:** 分四步执行,确保不丢 TDD、spec 合规和 code review 闸门:
223
+ 加载 `superpowers:subagent-driven-development`,由其驱动分派子 agent 每个独立 TDD + code review(transitive 激活)。
384
224
 
385
- **1. 先加载 `superpowers:test-driven-development` 技能设定 TDD 预期:**
386
- - 加载后,TDD 纪律(RED→GREEN→REFACTOR)成为本次执行的硬约束
387
- - 不在 executing-plans 内部"顺便做"——先设定预期,再执行
225
+ **构造子 agent 任务描述时,必须注入以下指令到任务描述末尾:**
226
+ > 实现完成时,在**同一个 commit** 中包含:实现代码 + 测试 + `openspec/changes/<name>/tasks.md` 中你负责的 task checkbox 从 `- [ ]` 改为 `- [x]`(含父级和子级)。不要分两个 commit。
388
227
 
389
- **技能加载后立即记录:**
390
- ```bash
391
- alloy _skill log openspec/changes/<name> apply superpowers:test-driven-development
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
- **3. executing-plans 完成后,进行 Spec 合规审查(Agent 自行检查,不加载额外技能):**
404
- - tasks.md 的每个 checkbox → 代码中是否有对应实现?
405
- - 代码中是否有 tasks.md 未要求的实现?(over-building)
406
- - plan.md 中明确排除的范围 → 代码是否碰了?
407
- - 不通过 → 修复 → 重新审查 → 通过后进入 code review
240
+ ---
408
241
 
409
- **4. 加载 `superpowers:requesting-code-review` 技能进行代码审查:**
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
- > superpowers:executing-plans 路径不会 transitive 激活 TDD、spec 合规或 code review。以上四步通过**显式加载**来补偿——先设定 TDD 预期,再执行,再校验 spec 合规,最后审查。
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
- > [Step 3/5] superpowers:verification-before-completion
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
- 验证失败 → 修复代码 → 回到 Step 2/5(SDD),确保修复也有 TDD + code review 安全网。
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
- **幂等检查:** 检查 verify.md 是否存在且 hash 有效:
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
- 1. 调用 `/opsx:verify` 执行结构化的 7 项检查
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. `/opsx:verify` 的输出由 OpenSpec CLI 生成,其语言不由 Agent 控制。Agent 拿到输出后,**必须将 verify.md 重写为与 `instructions/verify.md` 和 `templates/verify.md` 一致的语言**,不得直接透传 CLI 输出
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
- 7 项检查:结构校验 → 任务完成 → Delta Spec 同步 → Design/Specs 一致性 → 实现信号 → 路由泄漏检测 → 延期任务对照。
287
+ **opsx:verify 失败处理(⛔ HARD_STOP):**
467
288
 
468
- 验证失败 → 修复 → 回到 Step 2/5(SDD)。verify 不通过不结束 apply
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 ✓ 完成([N/M] 是阶段内局部编号,M=2,不是全局 8 制品编号)
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
- > 下一个:retrospective
483
- > (a) 确认,锁定 verify 并继续 retrospective
484
- > → (b) 需要调整 — 说明修改点,修改后重新展示
307
+ > 违反字面 = 违反精神:哪怕 verify.md 看似"明显合理",没经过用户明确选择 (a) = 不算授权。
308
+ > 禁止 agent 基于"diff 短"或"全 PASS"自动跳过此 USER_GATE,必须完整阅读 diff。
485
309
 
486
- 选 (a):hash 锁定 verify commit:
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
- git add openspec/changes/<name>/verify.md
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):调整 verify 内容后重新展示审查窗口。
321
+ 选 (b):重新生成 verify.md(不是直接编辑),重新展示审查窗口。
322
+
323
+ > [N/M] 是阶段内局部编号(M=2),不输出全局制品进度。全局进度由 `alloy status` 管理。
497
324
 
498
325
  ### [Step 5/5] 复盘
499
326
 
500
- **幂等检查:** 检查 retrospective.md 是否存在且 hash 有效:
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 5/5 进度检测:
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
- **输出语言与 `instructions/retrospective.md` `templates/retrospective.md` 保持一致。** 代码标识符、commit hash、文件名保持原始语言。
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
- **PRECHECK:** verify.md 存在且 Overall Decision 不是 FAIL,否则 STOP。
345
+ 失败 → ⛔ `[PRECONDITION_FAIL] verify 上游 hash 失效——verify.md 可能被未审批修改`。禁止 agent 自动重新锁定,必须用户审查后决定。
527
346
 
528
- **§0 量化全景:** 三来源自动收集——`.alloy.yaml` records(制品审批链)+ `git log`(全周期 commit,按 type 和阶段分组)+ 文件系统(任务完成比、变更规模、测试覆盖信号)。
347
+ 读取 `instructions/retrospective.md`,按 `templates/retrospective.md` 生成。输出语言与模板一致。代码标识符、commit hash、文件名保持原文。
529
348
 
530
- **§1 Wins:** `[evidence: ...]` 格式,聚焦可复现的成功模式。
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
- **§2 Misses:** 🔴 blocking / 🟡 painful / 📌 nit 三级严重度。
351
+ **Retrospective 跳过判定(🔴 USER_GATE + HARD_STOP,task #17):**
533
352
 
534
- **§3 Plan Deviations:** 计划 vs 实际变更表格,含 strategy 偏差说明。
353
+ 复盘是证据驱动的——每条结论引用具体 commit 或文件。判定流程:
535
354
 
536
- **§4 全周期技能审计:** 从 `.alloy.yaml` 的 `skill_usage[]` 字段读取 start/plan/apply/archive/finish 五阶段技能使用记录。`skill_usage[]` 为空(旧 change)→ 对应行填 `—`,不推断。跳过的技能展开三问(跳过什么/为什么/如何防复发)。
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
- **§5 Surprises:** 被推翻的假设。
361
+ - `COMMIT_COUNT == 1` 时:可能符合"单 commit 小修跳过"条件,但 **🔴 USER_GATE(必须 AskUserQuestion,不得 agent 自动选):**
539
362
 
540
- **§6 Promote Candidates:** `- [ ]` checklist + Why/How to apply,跨周期 carry-forward。标记 `Promote to: memory` 的条目在 archive 阶段由 Agent 写入 memory。
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
- 复盘是证据驱动的——每条结论都引用具体 commit 或文件。
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
- > 下一个:完成 apply 阶段
552
- > → (a) 确认,锁定 retrospective 并完成 apply
553
- > → (b) 需要调整 — 说明修改点,修改后重新展示
380
+ > 违反字面 = 违反精神:禁 agent 基于"内容看起来挺全"自动跳过此 USER_GATE。
554
381
 
555
- 选 (a):补填审批时间 + hash 锁定 + 提交,一个 commit 包含所有累积变更(retrospective + 阶段完成时间 + worktree 状态),不拆开:
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):调整 retrospective 内容后重新展示审查窗口。
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
- │ 启动时间: phase_timings.apply.started_at 读取 │
578
- │ 完成时间: phase_timings.apply.completed_at 读取 │
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
- Phase: applied
584
- Worktree: <path 当前分支>
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 阶段 commit 规则:**
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
- 不需要穷举目录——Agent 根据项目上下文判断即可。比如项目用了 vite,看到 `.vite/` 就知道该 ignore。判断不准时,询问用户确认。
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
+ ```