specline 1.3.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -125
- package/adapters/claude/deploy.json +12 -0
- package/adapters/claude/hooks/hooks.json +12 -0
- package/adapters/claude/hooks.json +12 -0
- package/adapters/claude/orchestration.md +17 -0
- package/adapters/codex/agent.toml.hbs +7 -0
- package/adapters/codex/deploy.json +12 -0
- package/adapters/codex/hooks.json +12 -0
- package/adapters/codex/orchestration.md +18 -0
- package/adapters/cursor/deploy.json +12 -0
- package/adapters/cursor/hooks.json +9 -0
- package/adapters/cursor/orchestration.md +17 -0
- package/adapters/opencode/deploy.json +12 -0
- package/adapters/opencode/orchestration.md +18 -0
- package/adapters/opencode/plugin.js +10 -0
- package/cli.mjs +161 -558
- package/core/agents/specline-backend-dev.yaml +45 -0
- package/core/agents/specline-code-reviewer.yaml +67 -0
- package/core/agents/specline-config-dev.yaml +50 -0
- package/core/agents/specline-config-reviewer.yaml +70 -0
- package/core/agents/specline-explore-assistant.yaml +79 -0
- package/core/agents/specline-frontend-dev.yaml +45 -0
- package/core/agents/specline-spec-creator.yaml +58 -0
- package/core/agents/specline-spec-reviewer.yaml +58 -0
- package/core/agents/specline-test-runner.yaml +62 -0
- package/core/agents/specline-test-writer.yaml +67 -0
- package/core/bootstrap/using-specline.md +14 -0
- package/core/gates/pipeline-gate-checks/a1-covers-ref.sh +125 -0
- package/core/gates/pipeline-gate-checks/a2-a3-reverse.sh +171 -0
- package/core/gates/pipeline-gate-checks/c1-exception.sh +71 -0
- package/core/gates/pipeline-gate-checks/c2-vague.sh +60 -0
- package/core/gates/pipeline-gate-checks/common.sh +68 -0
- package/core/gates/pipeline-gate-checks/d1-cycle.sh +149 -0
- package/core/gates/pipeline-gate-checks/d3-type-file.sh +260 -0
- package/core/gates/pipeline-gate.sh +1456 -0
- package/core/hooks/session-start.sh +259 -0
- package/core/skills/specline-apply-change/SKILL.md +197 -0
- package/core/skills/specline-archive-change/SKILL.md +173 -0
- package/core/skills/specline-explore/SKILL.md +504 -0
- package/core/skills/specline-knowledge/SKILL.md +539 -0
- package/core/skills/specline-pipeline/SKILL.md +604 -0
- package/core/skills/specline-pipeline/references/error-recovery-details.md +49 -0
- package/core/skills/specline-pipeline/references/event-log-spec.md +59 -0
- package/core/skills/specline-pipeline/references/pipeline-state-schema.md +87 -0
- package/core/skills/specline-pipeline/templates/subagent-prompts.md +397 -0
- package/core/skills/specline-propose/SKILL.md +186 -0
- package/core/skills/specline-quickfix/SKILL.md +289 -0
- package/core/templates/AGENTS.md.hbs +5 -0
- package/core/templates/specline/config.yaml +15 -0
- package/lib/deploy-claude.mjs +80 -0
- package/lib/deploy-codex.mjs +77 -0
- package/lib/deploy-opencode.mjs +93 -0
- package/lib/deploy.mjs +668 -0
- package/lib/gate.mjs +103 -0
- package/lib/hash.mjs +13 -0
- package/lib/hook.mjs +105 -0
- package/lib/init.mjs +122 -0
- package/lib/lock.mjs +99 -0
- package/lib/merge.mjs +184 -0
- package/lib/paths.mjs +40 -0
- package/lib/platforms.mjs +74 -0
- package/lib/render-agents.mjs +88 -0
- package/lib/render.mjs +126 -0
- package/lib/sync.mjs +253 -0
- package/lib/tty-select.mjs +89 -0
- package/package.json +4 -1
- package/templates/.cursor/README.md +18 -0
- package/templates/.cursor/agents/specline-code-reviewer.md +63 -4
- package/templates/.cursor/agents/specline-spec-creator.md +120 -1
- package/templates/.cursor/agents/specline-spec-reviewer.md +21 -2
- package/templates/.cursor/agents/specline-test-runner.md +10 -1
- package/templates/.cursor/agents/specline-test-writer.md +58 -7
- package/templates/.cursor/hooks/specline-pipeline-gate-checks/a2-a3-reverse.sh +1 -1
- package/templates/.cursor/hooks/specline-pipeline-gate.sh +118 -0
- package/templates/.cursor/skills/specline-apply-change/SKILL.md +26 -0
- package/templates/.cursor/skills/specline-archive-change/SKILL.md +24 -0
- package/templates/.cursor/skills/specline-explore/SKILL.md +17 -0
- package/templates/.cursor/skills/specline-knowledge/SKILL.md +539 -0
- package/templates/.cursor/skills/specline-pipeline/SKILL.md +102 -3
- package/templates/.cursor/skills/specline-pipeline/templates/subagent-prompts.md +32 -0
- package/templates/.cursor/skills/specline-propose/SKILL.md +34 -3
- package/templates/.cursor/skills/specline-quickfix/SKILL.md +26 -0
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specline-pipeline
|
|
3
|
+
description: >-
|
|
4
|
+
开发流水线元 Skill。编排 Spec → Coding → Review → Test → Archive 全流程,
|
|
5
|
+
调度子 Agent 和 Gate 脚本,支持断点续跑。输入自然语言需求自动推进到归档。
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# /specline-pipeline 开发流水线编排 Skill
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Layer 0: Session 绑定
|
|
13
|
+
|
|
14
|
+
Session 通过 `specline gate bind <session_id> <change>` 绑定到 Pipeline。
|
|
15
|
+
绑定后 sessionStart Hook 自动注入阶段上下文,归档时自动解绑。
|
|
16
|
+
切换 Pipeline 需在安全切换点(Gate 之后、批次之间)执行。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Layer 1: 速览与定位
|
|
21
|
+
|
|
22
|
+
你是**流水线编排者**,不是执行者。
|
|
23
|
+
|
|
24
|
+
**你做:**
|
|
25
|
+
- 读取 `.pipeline-state.json` 确定当前阶段和恢复点
|
|
26
|
+
- 启动子 Agent,按批次并发派发 coding Agent
|
|
27
|
+
- 显式调用 `specline gate` 进行门禁校验
|
|
28
|
+
- 根据 exit code 决策:前进 / 回退修复 / 暂停等人工确认
|
|
29
|
+
|
|
30
|
+
**你不做:**
|
|
31
|
+
- 需求判断/Spec 编写、代码编写、代码审查、测试编写、门禁判断——这些都交给子 Agent 和 Gate 脚本
|
|
32
|
+
|
|
33
|
+
### Phase 流程图
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
SPEC ──→ CODING ──→ CODE REVIEW ──→ TEST ──→ ARCHIVE
|
|
37
|
+
│G │G │G │G │G
|
|
38
|
+
🟡HG (并行) │G (串行) 🟡HG
|
|
39
|
+
🟡HG
|
|
40
|
+
|
|
41
|
+
G = Gate(确定性门禁脚本,零 LLM 参与)
|
|
42
|
+
🟡 = Human Gate(人工确认检查点)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 人机门禁策略
|
|
46
|
+
|
|
47
|
+
流水线有 3 个人工确认点:HG1(SPEC 确认)、HG2(Review 条件复核)、HG3(归档确认)。通过 `specline/config.yaml` 中的 `pipeline.human_gate_policy` 控制哪些 HG 需要人工确认:
|
|
48
|
+
|
|
49
|
+
| 策略 | HG1 (SPEC确认) | HG2 (Review复核) | HG3 (归档确认) |
|
|
50
|
+
|------|:-------------:|:----------------:|:-------------:|
|
|
51
|
+
| `full`(默认) | 人工确认 | 条件人工复核 | 人工确认 |
|
|
52
|
+
| `minimal` | 自动通过 | 自动通过 | 人工确认 |
|
|
53
|
+
| `none` | 自动通过 | 自动通过 | 自动通过 |
|
|
54
|
+
|
|
55
|
+
**读取方式**:在每个 HG 触发前读取 `specline/config.yaml` 的 `pipeline.human_gate_policy` 字段(通过 grep/yq),若策略指示跳过当前 HG,则直接写入 `.pipeline-state.json` 中对应 `human_gate_N.passed = true`,不调用 {{CONFIRM}}。
|
|
56
|
+
|
|
57
|
+
**子 Agent 确认行为**:当策略为 `minimal` 或 `none` 时,编排者应在派发子 Agent 时传递 `HUMAN_GATE_POLICY=<policy>` 上下文,告知子 Agent 跳过所有 {{CONFIRM}} 交互(如 spec_ambiguity 暂停、skill 级确认等),直接采用默认安全选项继续执行。编排者自身在测试失败处理中的 spec_ambiguity 暂停也应改为记录 WARNING 事件日志后继续。
|
|
58
|
+
|
|
59
|
+
### 入口模式
|
|
60
|
+
|
|
61
|
+
1. **新建流水线**: `/specline-pipeline <自然语言需求>`
|
|
62
|
+
2. **恢复流水线**: `/specline-pipeline --change <change-name>`
|
|
63
|
+
3. **自动发现**: `/specline-pipeline`(无参数,列出所有未完成流水线)
|
|
64
|
+
|
|
65
|
+
### 最终产出
|
|
66
|
+
|
|
67
|
+
归档到 `specline/changes/archive/YYYY-MM-DD-<name>/`
|
|
68
|
+
|
|
69
|
+
### Quickfix vs Pipeline 边界判断
|
|
70
|
+
|
|
71
|
+
**Quickfix vs Pipeline**:小改动(1-3 文件、单一关注点)使用 `/specline-quickfix`,多功能/跨模块改动使用 `/specline-pipeline`。详细对比见 `specline-quickfix` Skill。
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Core Operating Behaviors
|
|
76
|
+
|
|
77
|
+
以下守则对编排者自身和所有派发的子 Agent 均生效。编排者在决策(跳过 Gate、手动修复、忽略警告)时同样接受这些守则的约束。
|
|
78
|
+
|
|
79
|
+
### 1. Surface Assumptions
|
|
80
|
+
|
|
81
|
+
执行任何非平凡操作前,显式列出假设:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
ASSUMPTIONS I'M MAKING:
|
|
85
|
+
1. [关于需求的假设]
|
|
86
|
+
2. [关于架构的假设]
|
|
87
|
+
3. [关于范围的假设]
|
|
88
|
+
→ 现在纠正,否则我将按这些假设继续。
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
不要默默填补模糊需求。错误的假设是最昂贵的返工来源。
|
|
92
|
+
|
|
93
|
+
### 2. Manage Confusion Actively
|
|
94
|
+
|
|
95
|
+
遇到矛盾、冲突需求或模糊规范时:
|
|
96
|
+
|
|
97
|
+
1. **STOP** — 不要猜
|
|
98
|
+
2. 明确命名具体困惑点
|
|
99
|
+
3. 呈现权衡或提出澄清问题
|
|
100
|
+
4. 等待解决后再继续
|
|
101
|
+
|
|
102
|
+
**错误做法**:默默选择一种解释,祈祷它是正确的。
|
|
103
|
+
**正确做法**:"Spec 说 X 但现有代码是 Y。以哪个为准?"
|
|
104
|
+
|
|
105
|
+
### 3. Push Back When Warranted
|
|
106
|
+
|
|
107
|
+
你不是应声虫。当一个方案有明显问题时:
|
|
108
|
+
|
|
109
|
+
- 直接指出问题
|
|
110
|
+
- 解释具体代价(量化:"这会增加 ~200ms 延迟",而非"可能变慢")
|
|
111
|
+
- 提出替代方案
|
|
112
|
+
- 如果用户在有完整信息的情况下仍然坚持,接受决定
|
|
113
|
+
|
|
114
|
+
谄媚是失败模式。"当然可以!"然后实现一个糟糕的方案对谁都没好处。
|
|
115
|
+
|
|
116
|
+
### 4. Enforce Simplicity
|
|
117
|
+
|
|
118
|
+
主动抵抗复杂化的自然倾向。完成任何实现前问自己:
|
|
119
|
+
|
|
120
|
+
- 可以用更少的行数实现吗?
|
|
121
|
+
- 这些抽象真的值得它们的复杂度吗?
|
|
122
|
+
- 一个资深工程师看了会说"你为什么不直接……"吗?
|
|
123
|
+
|
|
124
|
+
1000 行能做的事用了 100 行是成功,100 行能做的事用了 1000 行是失败。
|
|
125
|
+
|
|
126
|
+
### 5. Maintain Scope Discipline
|
|
127
|
+
|
|
128
|
+
只碰你被要求碰的。不:
|
|
129
|
+
- "清理"与你任务无关的代码
|
|
130
|
+
- 顺便重构相邻系统
|
|
131
|
+
- 删除看起来没用的代码(未经明确批准)
|
|
132
|
+
- 添加 Spec 中没有的"看起来有用"的功能
|
|
133
|
+
|
|
134
|
+
你的工作是外科手术式精确修改,不是主动翻新。
|
|
135
|
+
|
|
136
|
+
### 6. Verify, Don't Assume
|
|
137
|
+
|
|
138
|
+
"看起来对"永远不够——必须有证据(通过的测试、构建输出、运行时数据)。编排者自身在 Gate 决策中也不例外:Gate 脚本的 exit code 是唯一判断依据,"看着应该通过了"不算数。
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Layer 2: Happy Path — 新建流水线
|
|
143
|
+
|
|
144
|
+
### Phase 1: SPEC
|
|
145
|
+
|
|
146
|
+
#### Step 1: 创建 Change
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
specline gate new --change "<kebab-case-name>"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
初始化 `.pipeline-state.json`,关键字段:
|
|
153
|
+
|
|
154
|
+
| 字段 | 说明 |
|
|
155
|
+
|------|------|
|
|
156
|
+
| `current_phase` | 当前阶段(spec / coding / code_review / test / archive) |
|
|
157
|
+
| `phases.<phase>.status` | 阶段状态(pending / in_progress / completed) |
|
|
158
|
+
| `phases.<phase>.gates.<gate_name>.passed` | 门禁通过状态(null / true / false) |
|
|
159
|
+
| `phases.coding.tasks[]` | 编码任务列表(含 id / type / deps / batch / status / files) |
|
|
160
|
+
|
|
161
|
+
> 📋 完整 JSON Schema 见 [附录 A](#附录-a-pipeline-statejson-完整-schema)
|
|
162
|
+
|
|
163
|
+
#### Step 2: 启动 specline-spec-creator
|
|
164
|
+
|
|
165
|
+
specline-spec-creator 子 Agent 的职责是根据内联模板直接生成全部规划文件:
|
|
166
|
+
- `proposal.md` — 需求提案(What/Why/Scope)
|
|
167
|
+
- `design.md` — 技术设计(架构/决策/数据流)
|
|
168
|
+
- `tasks.md` — 任务拆解清单(含 Type/Depends/Covers/Files 标注)
|
|
169
|
+
- `specs/<capability>/spec.md` — 功能规格(Requirements/Scenarios)
|
|
170
|
+
|
|
171
|
+
{{DISPATCH}},role="specline-spec-creator",描述中传入 change name 和自然语言需求,让 specline-spec-creator 根据内联模板直接生成。
|
|
172
|
+
|
|
173
|
+
> **任务标注规范**:tasks.md 每个任务必须包含:
|
|
174
|
+
> - `Type`: frontend | backend | infra | db | config | docs
|
|
175
|
+
> - `Depends`: (none) | 任务编号
|
|
176
|
+
> - `Covers`: Requirement: xxx, Scenario: xxx(链接到 Spec,必填)
|
|
177
|
+
> - `Files`: 相对路径,列出本任务将修改/创建的所有文件(必填,用于冲突检测)
|
|
178
|
+
|
|
179
|
+
> **注意**:specline-spec-creator 直接按内联模板生成 4 个 Artifact 并自检输出完整性(含并行度 ≥ 60% 和 Files 无冲突自检)。
|
|
180
|
+
|
|
181
|
+
完成后写入状态:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
185
|
+
jq --arg time "$NOW" '.updated_at = $time | .phases.spec.sub_phases["specline-spec-creator"] = {"status": "completed", "completed_at": $time}' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### Step 3: 审核全部规划文件(specline-spec-reviewer)
|
|
189
|
+
|
|
190
|
+
specline-spec-reviewer 审核三份文件:
|
|
191
|
+
1. `specs/` 下所有 spec.md 的完整性和一致性
|
|
192
|
+
2. `design.md` 的技术决策合理性和覆盖完整性
|
|
193
|
+
3. `tasks.md` 的格式、独立性、覆盖度、文件冲突
|
|
194
|
+
|
|
195
|
+
产出 spec-review.json (`{ "status": "approved"|"rejected", "feedback": [...], "coverage": {...}, "task_stats": {...} }`)。
|
|
196
|
+
|
|
197
|
+
若 rejected:将 feedback 反馈给用户修改,或手动编辑相应文件后重新审核(最多 3 次循环)。
|
|
198
|
+
|
|
199
|
+
#### Step 4: Spec Gate
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
specline gate spec --change "<name>"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
校验内容:`proposal.md` + `design.md` + `tasks.md` 存在且每个任务标注完整(Type/Depends/Covers/Files),每个 Requirement 至少被 1 个 task 引用,第 1 批次 Files 无重叠,至少 1 个任务 Depends: (none)。
|
|
206
|
+
|
|
207
|
+
exit code 0 = 通过,写入 passed。exit code != 0 = 失败,读取 stderr 展示给用户。
|
|
208
|
+
|
|
209
|
+
#### Step 5: 人工确认 (Human Gate 1) 🟡
|
|
210
|
+
|
|
211
|
+
> **策略判断**:读取 `specline/config.yaml` → `pipeline.human_gate_policy`。若为 `minimal` 或 `none` → 跳过此 HG,直接写入 `human_gate_1.passed = true`,进入 Phase 2。
|
|
212
|
+
|
|
213
|
+
Spec Gate 通过后,使用 {{CONFIRM}} 请求确认。展示内容包括:需求提案摘要、功能需求列表、任务拆解概览(含并行组)。
|
|
214
|
+
|
|
215
|
+
Human Gate 1 具体交互:使用 {{CONFIRM}},title="确认 Spec 和任务规划",选项:`approve`(确认通过,继续编码)/ `reject`(不通过,手动修改后重新审核)。
|
|
216
|
+
|
|
217
|
+
### Phase 2: CODING
|
|
218
|
+
|
|
219
|
+
> **并行加速**:Human Gate 1 通过后,**同时**启动 coding 和 specline-test-writer。specline-test-writer 是黑盒的——读取 Spec(验收标准)和 design.md(对外接口契约),不需要实现代码。两者并行可节省 specline-test-writer 的编写时间。
|
|
220
|
+
|
|
221
|
+
#### Step 6: 并行启动(test-writer + DAG 构建)
|
|
222
|
+
|
|
223
|
+
时序图:
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
时间 ────────────────────────────────────────────────────────────────────→
|
|
227
|
+
|
|
228
|
+
Track A (test-writer):
|
|
229
|
+
6a 启动 ───── specline-test-writer(黑盒,与 Coding 并行运行) ──────→ 等待 Step 12
|
|
230
|
+
|
|
231
|
+
Track B (coding):
|
|
232
|
+
6b 解析 tasks.md ──→ 6c 冲突检测 ──→ 7a 派发批次1 ──→ 7b 更新状态 ──→ 7c 派发批次2...
|
|
233
|
+
↓
|
|
234
|
+
Step 8: Build Gate
|
|
235
|
+
|
|
236
|
+
Track A 和 Track B 同时启动,互不阻塞。test-writer 在 Coding 全部完成后、TEST 阶段前被检查(Step 12)。
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**6a. 启动 specline-test-writer(与 Coding 阶段 Agent 同时启动)**:
|
|
240
|
+
|
|
241
|
+
{{DISPATCH}},role="specline-test-writer",prompt 中包含 changeName/Spec/Design/Tasks 路径和黑盒约束。test-writer 从 `design.md` 的「对外接口契约」章节获取 CLI 命令/HTTP 端点/模块导出签名(若章节不存在则在 prompt 中注明无需契约),从 spec.md 获取行为验收标准(WHEN/THEN)。specline-test-writer 只编写 tests/integration/** 和 tests/e2e/** 下的测试,产出 test-code-result.json。
|
|
242
|
+
|
|
243
|
+
**6b. 解析 tasks.md,构建任务 DAG**:
|
|
244
|
+
|
|
245
|
+
读取 `specline/changes/<name>/tasks.md`,解析每个任务的 `Type`、`Depends`、`Covers`、`Files` 标注,构建依赖关系图,划分为多个**并行批次**。
|
|
246
|
+
|
|
247
|
+
> **断点续跑时的任务状态恢复**:解析 tasks.md 时同时读取每个任务的 checkbox 状态(`[x]` 表示已完成,`[ ]` 表示未完成)。已完成的任务在 DAG 中标记为 `status: "completed"`,后续批次派发时自动跳过。
|
|
248
|
+
|
|
249
|
+
解析算法:
|
|
250
|
+
1. 用 grep 提取每个任务的 `Type`、`Depends`、`Covers`、`Files`、`Testable` 元数据
|
|
251
|
+
2. 批次划分:批次 1 = 所有 `Depends: (none)` 的任务,批次 N = 依赖仅限于 1..N-1 批次已完成任务的任务
|
|
252
|
+
3. 用 jq 构建任务列表写入状态文件,Testable 缺失默认为 false(向后兼容)
|
|
253
|
+
4. 断点续跑时同步 tasks.md 的 `[x]`/`[ ]` checkbox 状态到状态文件
|
|
254
|
+
|
|
255
|
+
**6c. 文件冲突检测(每批次派发前)**:
|
|
256
|
+
|
|
257
|
+
将当前批次所有任务的 `Files` 按路径前缀分为三类(`implementation` / `unit_test` / `other_test`),同类型文件重叠视为冲突。跨类型重叠不冲突(测试目录与实现目录天然隔离)。
|
|
258
|
+
|
|
259
|
+
#### Step 7: 按 Type 分组后并发派发 Coding Agent
|
|
260
|
+
|
|
261
|
+
对每个批次依次处理:
|
|
262
|
+
|
|
263
|
+
**7a. 同一批次内,先按角色(role)分组,再并发派发各角色组**:
|
|
264
|
+
|
|
265
|
+
Type → role 映射:
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
Type: frontend → role: "specline-frontend-dev"
|
|
269
|
+
Type: backend → role: "specline-backend-dev"
|
|
270
|
+
Type: infra → role: "specline-backend-dev"(基础设施类,用后端 agent 处理)
|
|
271
|
+
Type: db → role: "specline-backend-dev"(数据库迁移,用后端 agent 处理)
|
|
272
|
+
Type: config → role: "specline-config-dev"(shell 脚本、配置文件、JSON/YAML)
|
|
273
|
+
Type: docs → role: "specline-config-dev"(Markdown 文档、Skill 定义)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**分组规则**:将当前批次的所有任务按 role 分组。
|
|
277
|
+
|
|
278
|
+
**派发规则**:
|
|
279
|
+
- 同角色组内有 **≥2 个任务** → 使用 Template 4(批量执行),一个 {{DISPATCH}} 处理该组全部任务
|
|
280
|
+
- 同角色组内仅 **1 个任务** → 使用 Template 1/2/3(单任务),保持向后兼容
|
|
281
|
+
- **不同角色组之间并发派发**,组内的批量代理顺序执行该组的任务
|
|
282
|
+
|
|
283
|
+
**上下文窗口安全限制**:每个子 Agent 最多处理 **3 个任务**。如果同角色组内超过 3 个任务,编排者应拆分为多个子 Agent(每组 ≤3 个任务)。编排者在填充批量模板前估算 prompt 长度,超过安全窗口时自动拆分。
|
|
284
|
+
|
|
285
|
+
\[template_selection]:
|
|
286
|
+
根据 task.type 和 task.testable 选择模板:
|
|
287
|
+
|
|
288
|
+
- 批量执行(N ≥ 2)→ Template 4
|
|
289
|
+
- 单任务 testable=true → Template 1 (TDD)
|
|
290
|
+
- 单任务 testable=false 且 frontend/backend/infra/db → Template 2 (Standard)
|
|
291
|
+
- 单任务 config/docs → Template 3 (Config/Docs)
|
|
292
|
+
|
|
293
|
+
\[task_block_composition]:
|
|
294
|
+
对于 Template 4,编排者为每个 task 生成任务区块。区块内容从对应单任务模板(Template 1/2/3)中提取 **从 `## 当前任务` 到 `## 产出报告`** 的部分(不含共享前置和上下文文件),按任务顺序拼接为 `${tasks}` 变量。
|
|
295
|
+
|
|
296
|
+
**7b. 等待当前批次所有 Agent 完成后**:
|
|
297
|
+
|
|
298
|
+
**单任务 Agent** 和 **批量 Agent** 的结果验证逻辑相同——逐 task 检查:
|
|
299
|
+
|
|
300
|
+
1. 验证每个 task 的产出报告(`specline/changes/<name>/.tmp/task-<id>-result.json`)
|
|
301
|
+
2. **对 Testable=true 的任务**,验证 `task-<id>-result.json` 中是否包含 `test_files` 字段且其值非空。如果 Testable=true 但 agent 未产出测试文件,标记为 warning 并记录到事件日志:
|
|
302
|
+
```
|
|
303
|
+
{"ts":"...","event":"tdd_warning","task":"<id>","reason":"Testable=true but no test_files produced"}
|
|
304
|
+
```
|
|
305
|
+
3. 更新状态文件中对应 task 的 `status` 和 `completed_at`
|
|
306
|
+
4. **验证 tasks.md 中对应任务的 checkbox 已从 `[ ]` 变为 `[x]`**(如果未标记,自动补标)
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# 更新状态文件
|
|
310
|
+
jq --arg task_id "1" --arg time "$NOW" '
|
|
311
|
+
.phases.coding.tasks |= map(
|
|
312
|
+
if .id == $task_id then .status = "completed" | .completed_at = $time else . end
|
|
313
|
+
)
|
|
314
|
+
' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
|
|
315
|
+
|
|
316
|
+
# 如果 Agent 忘记标记 tasks.md,自动补标
|
|
317
|
+
# sed 将 "## <task_id>. [ ]" 替换为 "## <task_id>. [x]"
|
|
318
|
+
sed -i '' "s/^## ${task_id}\. \[ \]/## ${task_id}. [x]/" specline/changes/<name>/tasks.md
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**7c. 检查是否有下一批次**。如有,回到 6c(冲突检测)→ 7a 继续派发。
|
|
322
|
+
|
|
323
|
+
#### Step 8: Build Gate
|
|
324
|
+
|
|
325
|
+
全部批次完成后,运行 Build Gate:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
specline gate build --change "<name>"
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Build Gate 校验内容:
|
|
332
|
+
- 编译/语法检查(原有逻辑)
|
|
333
|
+
- **单元测试文件存在性检查**(新增):对 Testable=true 的任务,检查其 `tests/unit/` 和 `tests/models/` 下的单元测试文件是否存在且语法正确。如果 Testable=true 的任务未产出对应测试文件,Build Gate 失败
|
|
334
|
+
- **对外接口契约签名检查**(新增):以 tasks.md 为决策源头——仅当 tasks.md 末尾「测试文件归属」表格中存在 specline-test-writer 负责的测试时,才检查 design.md 的「对外接口契约」章节:
|
|
335
|
+
- 有 test-writer 任务但缺契约章节 → 阻断(报错:缺契约)
|
|
336
|
+
- 有契约 → 逐项检查 CLI 命令注册、HTTP 路径注册、模块导出声明是否存在(只检查签名存在性,不检查语义正确性)
|
|
337
|
+
- 无 test-writer 任务 → 跳过
|
|
338
|
+
|
|
339
|
+
exit code 0 = 通过,进入 Phase 3。失败处理见 [Layer 3: Build Gate 失败处理](#build-gate-失败处理)。
|
|
340
|
+
|
|
341
|
+
### Phase 3: CODE REVIEW
|
|
342
|
+
|
|
343
|
+
#### Step 9: 启动审查 Agent
|
|
344
|
+
|
|
345
|
+
根据 tasks.md 中任务类型决定审查方式:
|
|
346
|
+
|
|
347
|
+
**9a. specline-code-reviewer**(有 frontend/backend/infra/db 类型任务时):
|
|
348
|
+
|
|
349
|
+
审查前端/后端代码变更。审查时利用 tasks.md 的 `Covers` 追溯链:每个 finding 应标注涉及的文件和对应的 Requirement/Scenario。
|
|
350
|
+
|
|
351
|
+
对 Testable=true 的任务,额外审查其 `tests/unit/` 和 `tests/models/` 下的单元测试文件质量,包括:
|
|
352
|
+
- 边界条件覆盖(空值、极值、边界值)
|
|
353
|
+
- 异常路径覆盖(错误输入、异常状态)
|
|
354
|
+
- 测试断言的有效性
|
|
355
|
+
|
|
356
|
+
code-review.json 中 unit test 相关的 finding 标注 `type` 为 `"unit_test_quality"`,示例:
|
|
357
|
+
```json
|
|
358
|
+
{ "severity": "warning", "type": "unit_test_quality", "file": "tests/unit/auth/test_login.py", "covers": "Requirement: Coding Agent Prompt 条件化 TDD 注入", "message": "缺少空密码输入边界条件测试" }
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**9b. specline-config-reviewer**(有 config/docs 类型任务时):
|
|
362
|
+
|
|
363
|
+
审查 config/docs 变更——shell 脚本安全性、配置文件语法和一致性、Markdown 文档结构完整性。
|
|
364
|
+
|
|
365
|
+
> 两种审查 Agent 可并发启动。产出均为 `specline/changes/<name>/.tmp/code-review.json`(`{ "findings": [{ "severity": "error"|"warning", "type": "unit_test_quality"|"style"|"security"|"logic", "file": "...", "covers": "Requirement: xxx", "message": "..." }] }`)。
|
|
366
|
+
|
|
367
|
+
#### Step 10: Lint Gate
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
specline gate lint --change "<name>"
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
检查 eslint/ruff 退出码 + code-review.json 中 error 计数。
|
|
374
|
+
|
|
375
|
+
失败 → 根据 findings 的 `file` 和 `covers` 字段定位到具体任务,只回对应 coding agent 修复(最多 2 次)。
|
|
376
|
+
|
|
377
|
+
#### Step 11: 可选人工复核 (Human Gate 2) 🟡
|
|
378
|
+
|
|
379
|
+
> **策略判断**:读取 `specline/config.yaml` → `pipeline.human_gate_policy`。若为 `minimal` 或 `none` → 跳过此 HG,直接写入 `human_gate_2.passed = true`,进入 Phase 4。
|
|
380
|
+
|
|
381
|
+
仅当 code-review.json 中 warnings > 0 且 errors = 0 时,使用 {{CONFIRM}} 询问是否人工复核(`skip` 自动继续 / `review` 展示警告详情)。
|
|
382
|
+
|
|
383
|
+
### Phase 4: TEST
|
|
384
|
+
|
|
385
|
+
> **config/docs 跳过测试**:如果 tasks.md 中所有任务均为 `Type: config` 或 `Type: docs`(无应用代码变更),TEST 阶段自动跳过——test-unit/integration/e2e Gate 在无测试目录时自动放行。流水线直接从 CODE REVIEW 进入 ARCHIVE。
|
|
386
|
+
|
|
387
|
+
#### Step 12: 确认 specline-test-writer 完成
|
|
388
|
+
|
|
389
|
+
specline-test-writer 已在 Phase 2(Step 6a)与 Coding 并行启动。进入 TEST 阶段时,检查 specline-test-writer 是否已完成:
|
|
390
|
+
|
|
391
|
+
- 已完成 → 读取 `specline/changes/<name>/.tmp/test-code-result.json` 获取 `test_framework`,写入 `.pipeline-state.json`:
|
|
392
|
+
```bash
|
|
393
|
+
FRAMEWORK=$(jq -r '.test_framework' specline/changes/<name>/.tmp/test-code-result.json)
|
|
394
|
+
jq --arg fw "$FRAMEWORK" '.phases.test.framework = $fw' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
|
|
395
|
+
```
|
|
396
|
+
然后直接进入测试执行
|
|
397
|
+
- 未完成 → 等待 specline-test-writer 完成(展示等待状态),完成后同上写入框架信息
|
|
398
|
+
|
|
399
|
+
> `test_framework` 写入状态文件后,后续 `specline gate` 的 test gate 会自动读取并选择正确的测试命令(Jest/pytest/go test 等)。
|
|
400
|
+
|
|
401
|
+
> **黑盒约束回顾**:specline-test-writer 只能基于 Spec 文档(验收标准)和 design.md 的「对外接口契约」章节(接口签名)编写测试,不能读取任何实现源代码。specline-test-writer 会自动检测项目测试框架(Jest/pytest/go test 等),按项目实际语言编写测试。
|
|
402
|
+
|
|
403
|
+
#### Step 13: 测试门禁链(串行)
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
# 单元测试
|
|
407
|
+
specline gate test-unit --change "<name>"
|
|
408
|
+
# 集成测试
|
|
409
|
+
specline gate test-integration --change "<name>"
|
|
410
|
+
# E2E 测试
|
|
411
|
+
specline gate test-e2e --change "<name>"
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
exit code 全 0 = 通过,进入 Phase 5。失败处理见 [Layer 3: 测试失败处理](#测试失败处理)。
|
|
415
|
+
|
|
416
|
+
### Phase 5: ARCHIVE
|
|
417
|
+
|
|
418
|
+
#### Step 14: 归档确认 (Human Gate 3) 🟡
|
|
419
|
+
|
|
420
|
+
> **策略判断**:读取 `specline/config.yaml` → `pipeline.human_gate_policy`。若为 `none` → 跳过此 HG,直接写入 `human_gate_3.passed = true`,执行归档。`minimal` 策略下 HG3 保留人工确认。
|
|
421
|
+
|
|
422
|
+
全部测试通过后,使用 {{CONFIRM}} 请求归档确认(`archive` 执行归档 / `cancel` 暂停流水线)。
|
|
423
|
+
|
|
424
|
+
#### Step 15: 归档
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
specline gate archive --execute --change "<name>"
|
|
428
|
+
specline gate archive --change "<name>"
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
> 归档的详细逻辑(Delta spec sync 决策、目录移动、摘要展示)由 **specline-archive-change** Skill 负责。编排者只需确认 Human Gate 3 通过后调用上述归档命令。
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
### 统一失败处理流程
|
|
436
|
+
|
|
437
|
+
所有 Gate 失败均按以下管道处理:
|
|
438
|
+
|
|
439
|
+
1. **诊断**:分析 stderr/exit code 确定失败类型(Build/Test/Hook)
|
|
440
|
+
2. **定位**:基于 Covers 追溯链定位到具体任务(Build 失败额外用 Depends 影响范围算法计算下游任务)
|
|
441
|
+
3. **修复**:回对应 agent 修复(最多 2 次循环)
|
|
442
|
+
4. **Gate 重置**:`jq '...gate.passed = null' "$STATE_FILE"`
|
|
443
|
+
5. **特殊规则**:
|
|
444
|
+
- `spec_ambiguity` → 暂停流水线展示模糊点(minimal/none 策略下降级为 WARNING)
|
|
445
|
+
- `contract_mismatch` → 优先回 coding agent 按契约修正(最多 2 次);2 次后仍不一致 → 暂停并报告用户确认
|
|
446
|
+
- 接口不兼容 → 只重置受影响的下游任务(保留未受影响任务的状态)
|
|
447
|
+
- Hook 阻断 → 先诊断原因 → 与用户沟通({{CONFIRM}})→ 修复后重试 → 绝不静默降级
|
|
448
|
+
- 测试失败优先级:单元测试优先于集成/E2E
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## Layer 3: 异常与恢复
|
|
453
|
+
|
|
454
|
+
### Build 失败差异化处理
|
|
455
|
+
|
|
456
|
+
- 单个任务构建失败 → 回对应 coding agent 修复(最多 2 次循环)
|
|
457
|
+
- 接口不兼容 → 使用影响范围算法(找到修改任务集合 M → 遍历 Depends → 递归扩展),只重置受影响的下游任务(未受影响任务保持 completed)
|
|
458
|
+
- Gate 重置:`jq '.phases.coding.gates.build_gate.passed = null' "$STATE_FILE"`
|
|
459
|
+
- 修复后只重跑受影响的任务(按原批次顺序)
|
|
460
|
+
|
|
461
|
+
### 测试失败差异化处理
|
|
462
|
+
|
|
463
|
+
- **单元测试失败**(`tests/unit/` / `tests/models/`):利用 Covers 追溯链定位 → 回 coding agent 修复(最多 2 次)
|
|
464
|
+
- Gate 重置:`jq '.phases.test.sub_phases.unit.gates.test_unit_gate.passed = null' "$STATE_FILE"`
|
|
465
|
+
- **集成/E2E 测试失败**(`tests/integration/` / `tests/e2e/`):先判断是测试代码还是实现代码问题
|
|
466
|
+
- 测试代码问题 → specline-test-writer 自修(最多 2 次)
|
|
467
|
+
- 实现代码问题 → Covers 追溯定位 → 回 coding agent 修复 → 用影响范围算法重置受影响 Gate
|
|
468
|
+
- **契约不一致** (`contract_mismatch`):实现代码的对外接口与 design.md 契约不一致 → 优先回 coding agent 按契约修正代码(最多 2 次);若 2 次后仍不一致,暂停并报告用户确认以 design.md 契约为准还是以代码为准
|
|
469
|
+
- Gate 重置:`.phases.test.sub_phases.integration.gates.test_integration_gate.passed = null | .phases.test.sub_phases.e2e.gates.test_e2e_gate.passed = null`
|
|
470
|
+
- **优先级**:单元测试失败优先修复;代码修复后所有测试 Gate 全部重置
|
|
471
|
+
|
|
472
|
+
### Hook 阻断差异化处理
|
|
473
|
+
|
|
474
|
+
⚠️ 编排者绝对不允许静默降级为自己直接执行。处理流程:
|
|
475
|
+
|
|
476
|
+
1. **识别原因**:判断权限/依赖/白名单/hooks.json 等问题
|
|
477
|
+
2. **与用户沟通**:使用 {{CONFIRM}} 展示诊断结果和修复选项(auto_fix / manual_fix / skip_agent)
|
|
478
|
+
3. **执行修复并重试**:auto_fix → 执行修复命令;manual_fix → 等待用户;skip_agent → 仅用户明确选择时降级(记录到事件日志)
|
|
479
|
+
4. **验证修复结果**:重试子 Agent,失败则重新诊断 → 再次沟通(最多 2 次循环)→ 仍失败则暂停并报告用户
|
|
480
|
+
|
|
481
|
+
此规范适用于所有 hook 阻断场景(`subagentStart`、`beforeShellExecution` 等)。
|
|
482
|
+
|
|
483
|
+
### 断点续跑流程
|
|
484
|
+
|
|
485
|
+
#### 发现未完成流水线
|
|
486
|
+
|
|
487
|
+
扫描 `specline/changes/*/.pipeline-state.json`:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
for f in specline/changes/*/.pipeline-state.json; do
|
|
491
|
+
PHASE=$(jq -r '.current_phase' "$f")
|
|
492
|
+
STATUS=$(jq -r '.phases."'"$PHASE"'".status' "$f")
|
|
493
|
+
if [ "$STATUS" != "completed" ] && [ "$PHASE" != "archive" ]; then
|
|
494
|
+
echo "$(basename $(dirname $f)): phase=$PHASE"
|
|
495
|
+
fi
|
|
496
|
+
done
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
**使用 {{CONFIRM}} 让用户选择:**
|
|
500
|
+
|
|
501
|
+
- 只有 1 个未完成 → 直接展示进度摘要确认
|
|
502
|
+
- 有多个未完成 → 动态构建选项列表,title="发现未完成流水线",列出各 change 名称及其阶段状态,让用户选择要继续的流水线。
|
|
503
|
+
|
|
504
|
+
#### 恢复算法
|
|
505
|
+
|
|
506
|
+
从后往前扫描 `phases` 中每个阶段的 `gates`,找到最后一个 `passed: true` 的门禁:
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
RESTORE_POINT="spec" # 默认从 spec 开始
|
|
510
|
+
|
|
511
|
+
for phase in archive test code_review coding spec; do
|
|
512
|
+
GATES=$(jq -r ".phases.${phase}.gates | keys[]" "$STATE_FILE" 2>/dev/null)
|
|
513
|
+
for gate in $GATES; do
|
|
514
|
+
PASSED=$(jq -r ".phases.${phase}.gates.${gate}.passed" "$STATE_FILE")
|
|
515
|
+
if [ "$PASSED" = "true" ]; then
|
|
516
|
+
# 找到最后通过的 gate,下一阶段为恢复点
|
|
517
|
+
case "$phase" in
|
|
518
|
+
spec) RESTORE_POINT="coding";;
|
|
519
|
+
coding) RESTORE_POINT="code_review";;
|
|
520
|
+
code_review) RESTORE_POINT="test";;
|
|
521
|
+
test) RESTORE_POINT="archive";;
|
|
522
|
+
esac
|
|
523
|
+
fi
|
|
524
|
+
done
|
|
525
|
+
done
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
#### 重置不可信子阶段
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
# 将恢复阶段中 completed_at 为空的子阶段重置为 pending
|
|
532
|
+
jq --arg phase "$RESTORE_POINT" '
|
|
533
|
+
if .phases[$phase].sub_phases then
|
|
534
|
+
.phases[$phase].sub_phases |= with_entries(
|
|
535
|
+
if .value.completed_at == null then
|
|
536
|
+
.value.status = "pending"
|
|
537
|
+
else . end
|
|
538
|
+
)
|
|
539
|
+
else . end
|
|
540
|
+
' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
#### 从 tasks.md 恢复已完成任务状态
|
|
544
|
+
|
|
545
|
+
恢复到 CODING 阶段时,必须先读取 tasks.md 的 checkbox 状态,与 `.pipeline-state.json` 交叉校验:
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
# 从 tasks.md 提取 checkbox 状态
|
|
549
|
+
# "## 1. [x]" → task 1 已完成, "## 2. [ ]" → task 2 未完成
|
|
550
|
+
grep -n '^## \d\+\.' specline/changes/<name>/tasks.md | while read line; do
|
|
551
|
+
task_id=$(echo "$line" | sed 's/.*## \([0-9]*\)\. .*/\1/')
|
|
552
|
+
if echo "$line" | grep -q '\[x\]'; then
|
|
553
|
+
# 同步到状态文件
|
|
554
|
+
jq --arg tid "$task_id" '
|
|
555
|
+
.phases.coding.tasks |= map(
|
|
556
|
+
if .id == $tid then .status = "completed" else . end
|
|
557
|
+
)' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
|
|
558
|
+
fi
|
|
559
|
+
done
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
这个交叉校验确保:即使 `.pipeline-state.json` 丢失或损坏,tasks.md 的 `[x]`/`[ ]` 标记仍可作为任务进度的可靠来源。
|
|
563
|
+
|
|
564
|
+
#### 展示恢复摘要
|
|
565
|
+
|
|
566
|
+
计算恢复点后,**直接开始恢复,不需要再次人工确认**(用户选择 pipeline 时已确认意图)。
|
|
567
|
+
|
|
568
|
+
如果只有一个未完成流水线,使用 {{CONFIRM}} 做一次快速确认:title="恢复流水线",展示变更名称、已完成阶段、未完成阶段,选项:`continue`(继续执行)/ `cancel`(取消)。
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
## Layer 4: 参考文档
|
|
573
|
+
|
|
574
|
+
> 以下文档为完整参考信息,根据需要查阅:
|
|
575
|
+
|
|
576
|
+
- State Schema → 详见 `references/pipeline-state-schema.md`
|
|
577
|
+
- Event Log → 详见 `references/event-log-spec.md`
|
|
578
|
+
- Hook & Constraints → 详见 `references/error-recovery-details.md`
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## Anti-Rationalization 表格
|
|
583
|
+
|
|
584
|
+
编排者在运作流水线时会找借口跳过步骤。以下是常见借口及其反驳:
|
|
585
|
+
|
|
586
|
+
| 借口 | 现实 |
|
|
587
|
+
|------|------|
|
|
588
|
+
| "这需求太简单了,不需要 Spec" | 简单需求也有隐含假设。Spec 的价值在于暴露假设,与复杂度无关。 |
|
|
589
|
+
| "Gate 跳过一次没关系" | Gate 是确定性脚本,跳过意味着自动化防线失效。一次跳过会变成习惯。 |
|
|
590
|
+
| "手工改一下比回子 Agent 修复快" | 手工改绕过了 Covers 追溯链和影响范围算法,下次断点续跑会丢失上下文。 |
|
|
591
|
+
| "测试最后一起跑" | Bug 会复合。阶段 1 的 Bug 让阶段 2-5 的产出都不可靠。每个阶段验证,不是事后验证。 |
|
|
592
|
+
| "HG 确认我替用户点了吧" | Human Gate 存在是因为这些决策需要人的判断。替用户确认等于架空人机门禁。 |
|
|
593
|
+
| "Build 失败看起来是子 Agent 的问题,我先继续往下" | 错误会传播。修复当前阶段再向下,否则下游建立在错误的基座上。 |
|
|
594
|
+
| "影响范围看起来不大,全重置就行" | 接口不兼容只应重置受影响的下游任务。全重置浪费已完成的工作,且破坏断点续跑的状态完整性。 |
|
|
595
|
+
|
|
596
|
+
## Verification Checklist
|
|
597
|
+
|
|
598
|
+
每阶段完成后,编排者自查:
|
|
599
|
+
|
|
600
|
+
- [ ] **SPEC 阶段**:4 Artifact 齐全(proposal/design/tasks/specs);Spec Gate 通过;HG1 已确认;spec-review.json status=approved
|
|
601
|
+
- [ ] **CODING 阶段**:全部批次完成;每个 task 产出报告存在;tasks.md checkbox 全部 [x];Build Gate 通过(含契约签名检查);Testable=true 任务的 test_files 非空
|
|
602
|
+
- [ ] **CODE REVIEW 阶段**:code-review.json 存在;error 计数 = 0;Lint Gate 通过;HG2 已处理
|
|
603
|
+
- [ ] **TEST 阶段**:test_framework 已写入状态文件;test-unit/integration/e2e Gate 全绿
|
|
604
|
+
- [ ] **ARCHIVE 阶段**:HG3 已确认;归档目录已创建;session 绑定已解除;Delta spec sync 决策已完成
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Hook 约束与速查表参考
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
本文档提供 Specline Pipeline 的 Hook 约束体系说明和关键约束速查表,供编排者在遇到 Hook 阻断、阶段不匹配等场景时查阅。内容对应原 SKILL.md 的附录 D(Hook 约束体系)和附录 E(关键约束速查表)。
|
|
6
|
+
|
|
7
|
+
## Hook 约束体系
|
|
8
|
+
|
|
9
|
+
Specline 通过 Cursor Hooks 提供了三层自动约束,确保在长对话中 Agent 不偏离流水线逻辑:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
sessionStart → specline-session-start.sh
|
|
13
|
+
新会话启动时检测活跃 pipeline,自动注入阶段上下文到 Agent 系统提示
|
|
14
|
+
|
|
15
|
+
preToolUse → specline-phase-guard.sh
|
|
16
|
+
操作前检查:SPEC 阶段拦截代码编辑、阶段不匹配的子Agent 启动
|
|
17
|
+
|
|
18
|
+
postToolUse → specline-reminder.sh
|
|
19
|
+
关键操作后注入提醒:更新 tasks.md checkbox、运行 Gate 脚本
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 对编排者的影响
|
|
23
|
+
|
|
24
|
+
1. **总是先检查** - preToolUse 会阻止不匹配当前阶段的操作,所以你在行动前自然会考虑阶段
|
|
25
|
+
2. **被提醒下一步** - postToolUse 在子Agent完成后提醒你更新 checkbox 和运行 Gate
|
|
26
|
+
3. **非流水线会话无影响** - 所有 Hook 的第一步检查「是否有活跃 pipeline」,无则透明放行
|
|
27
|
+
|
|
28
|
+
### 约束策略表
|
|
29
|
+
|
|
30
|
+
| 场景 | 策略 | 原因 |
|
|
31
|
+
|------|------|------|
|
|
32
|
+
| SPEC 阶段编辑代码文件 | **硬拦截 (deny)** | 明确违规 |
|
|
33
|
+
| SPEC 阶段启动编码 Agent | **硬拦截 (deny)** | 阶段不匹配 |
|
|
34
|
+
| CODING 阶段直接编辑代码 | **软提醒 (postToolUse)** | Hook 无法区分编排者和子Agent的 Write |
|
|
35
|
+
| 子Agent完成后忘记 Gate | **软提醒 (postToolUse)** | 操作后注入下一步提醒 |
|
|
36
|
+
|
|
37
|
+
> 注意:CODING 阶段 Orchestrator 直接编辑代码文件不会被 Hook 硬拦截(因为子Agent 也需要 Write 权限),但 SKILL 指令和 sessionStart 注入的上下文会持续提醒你「编码应通过子 Agent」。如果你发现自己想直接编辑代码,停一下,改用 Task 工具。
|
|
38
|
+
|
|
39
|
+
## 关键约束速查表
|
|
40
|
+
|
|
41
|
+
| # | 约束 | 说明 |
|
|
42
|
+
|---|------|------|
|
|
43
|
+
| 1 | **不做判断,只做编排** | 不评估代码质量、需求好坏、测试覆盖——这些由子 Agent 和 Gate 脚本负责 |
|
|
44
|
+
| 2 | **所有门禁通过 Gate 脚本** | 调用 `specline gate`,不要自己写 grep/检查逻辑 |
|
|
45
|
+
| 3 | **状态文件是唯一真相源** | 所有决策基于 `.pipeline-state.json` 的当前值 |
|
|
46
|
+
| 4 | **人工确认点必须尊重策略** | 根据 `pipeline.human_gate_policy` 配置决定是否暂停,不要无条件跳过或强制暂停 human_gate |
|
|
47
|
+
| 5 | **测试 Agent 必须黑盒** | 不给 specline-test-writer 传递源代码文件路径 |
|
|
48
|
+
| 6 | **Hook 阻断绝不静默降级** | 子 Agent 被 hook 阻止时,必须先诊断、沟通、修复后重试 |
|
|
49
|
+
| 7 | **接受 Hook 约束** | preToolUse/postToolUse/sessionStart Hook 会自动校验和提醒,不要试图绕过 |
|