specline 1.0.0 → 1.1.1

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.
@@ -7,109 +7,67 @@ description: >-
7
7
 
8
8
  # /specline-pipeline 开发流水线编排 Skill
9
9
 
10
- ## 角色定位
10
+ ---
11
+
12
+ ## Layer 1: 速览与定位
11
13
 
12
14
  你是**流水线编排者**,不是执行者。
13
15
 
14
16
  **你做:**
15
17
  - 读取 `.pipeline-state.json` 确定当前阶段和恢复点
16
- - 启动子 Agent(specline-spec-creator, specline-spec-reviewer, specline-frontend-dev, specline-backend-dev, specline-code-reviewer, specline-test-writer, specline-test-runner)
17
- - 解析 `tasks.md` 构建任务依赖 DAG,按批次并发派发 coding Agent
18
+ - 启动子 Agent,按批次并发派发 coding Agent
18
19
  - 显式调用 `specline-pipeline-gate.sh` 进行门禁校验
19
20
  - 根据 exit code 决策:前进 / 回退修复 / 暂停等人工确认
20
- - 写入状态文件(子 Agent 完成后写入 `completed_at`)
21
21
 
22
22
  **你不做:**
23
- - 需求判断和 Spec 编写(由 specline-spec-creator 直接生成 4 个规划文件)
24
- - 代码审查(由 specline-code-reviewer 负责)
25
- - 门禁判断(由 specline-pipeline-gate.sh 负责,零 LLM 参与)
26
- - 代码编写(由 coding agents 负责)
27
- - 测试编写(由 specline-test-writer 负责)
28
-
29
- ## 入口模式
30
-
31
- 1. **新建流水线**: `/specline-pipeline <自然语言需求>`
32
- 2. **恢复流水线**: `/specline-pipeline --change <change-name>`
33
- 3. **自动发现**: `/specline-pipeline`(无参数,列出所有未完成流水线)
34
-
35
- ## 用户交互规范(省 request)
23
+ - 需求判断/Spec 编写、代码编写、代码审查、测试编写、门禁判断——这些都交给子 Agent Gate 脚本
36
24
 
37
- **所有需要用户做选择的交互,必须使用 `AskUserQuestion` 工具而非自由文本询问。** 结构化问题能让 Cursor 在单次请求中完成交互,避免额外轮次。
25
+ ### Phase 流程图
38
26
 
39
- 使用模式:
40
- ```javascript
41
- AskUserQuestion({
42
- title: "简洁标题",
43
- questions: [{
44
- id: "unique_id",
45
- prompt: "问题描述",
46
- options: [
47
- { id: "option_a", label: "选项 A 的描述" },
48
- { id: "option_b", label: "选项 B 的描述" }
49
- ],
50
- allow_multiple: false // 单选;需要多选时设为 true
51
- }]
52
- })
53
27
  ```
28
+ SPEC ──→ CODING ──→ CODE REVIEW ──→ TEST ──→ ARCHIVE
29
+ │G │G │G │G │G
30
+ 🟡HG (并行) │G (串行) 🟡HG
31
+ 🟡HG
54
32
 
55
- 各场景示例见下方。
33
+ G = Gate(确定性门禁脚本,零 LLM 参与)
34
+ 🟡 = Human Gate(人工确认检查点)
35
+ ```
56
36
 
57
- ## 流水线阶段定义
37
+ ### 入口模式
58
38
 
59
- ```
60
- PHASE 1: SPEC
61
- specline-spec-creator(直接生成 4 个 Artifact)→ specline-spec-reviewer
62
- → GATE: specline-pipeline-gate.sh spec
63
- → 🟡 HUMAN GATE: 人工确认 Spec & 任务规划
39
+ 1. **新建流水线**: `/specline-pipeline <自然语言需求>`
40
+ 2. **恢复流水线**: `/specline-pipeline --change <change-name>`
41
+ 3. **自动发现**: `/specline-pipeline`(无参数,列出所有未完成流水线)
64
42
 
65
- PHASE 2: CODING
66
- 解析 tasks.md → 按依赖层级分批并发派发 coding agents
67
- → GATE: specline-pipeline-gate.sh build
43
+ ### 最终产出
68
44
 
69
- PHASE 3: CODE REVIEW
70
- specline-code-reviewer → code-review.json
71
- → GATE: specline-pipeline-gate.sh lint
72
- → 🟡 HUMAN GATE: warnings 可选复核
45
+ 归档到 `specline/changes/archive/YYYY-MM-DD-<name>/`
73
46
 
74
- PHASE 4: TEST
75
- 单元测试 → GATE → 集成测试 → GATE → E2E → GATE
76
- (specline-test-writer 为黑盒,不能看实现代码)
47
+ ---
77
48
 
78
- PHASE 5: ARCHIVE
79
- → 🟡 HUMAN GATE: 归档确认
80
- → specline-pipeline-gate.sh archive --execute --change <change>
81
- → GATE: specline-pipeline-gate.sh archive
82
- ```
49
+ ## Layer 2: Happy Path — 新建流水线
83
50
 
84
- ## 新建流水线执行流程 (Phase 1: SPEC)
51
+ ### Phase 1: SPEC
85
52
 
86
- ### Step 1: 创建 Change
53
+ #### Step 1: 创建 Change
87
54
 
88
55
  ```bash
89
56
  specline-pipeline-gate.sh new --change "<kebab-case-name>"
90
57
  ```
91
58
 
92
- 初始化 `.pipeline-state.json`:
59
+ 初始化 `.pipeline-state.json`,关键字段:
93
60
 
94
- ```json
95
- {
96
- "version": 1,
97
- "change_name": "<name>",
98
- "created_at": "<ISO8601>",
99
- "updated_at": "<ISO8601>",
100
- "current_phase": "spec",
101
- "current_step": "specline-spec-creator",
102
- "phases": {
103
- "spec": { "status": "in_progress", "retry_count": 0, "sub_phases": {}, "gates": { "spec_gate": { "passed": null }, "human_gate_1": { "passed": null } } },
104
- "coding": { "status": "pending", "tasks": [], "sub_phases": {}, "gates": { "build_gate": { "passed": null } } },
105
- "code_review": { "status": "pending", "retry_count": 0, "gates": { "lint_gate": { "passed": null }, "human_gate_2": { "passed": null } } },
106
- "test": { "status": "pending", "framework": null, "sub_phases": { "unit": { "status": "pending", "gates": { "test_unit_gate": { "passed": null } } }, "integration": { "status": "pending", "gates": { "test_integration_gate": { "passed": null } } }, "e2e": { "status": "pending", "gates": { "test_e2e_gate": { "passed": null } } } } },
107
- "archive": { "status": "pending", "gates": { "human_gate_3": { "passed": null }, "archive_gate": { "passed": null } } }
108
- }
109
- }
110
- ```
61
+ | 字段 | 说明 |
62
+ |------|------|
63
+ | `current_phase` | 当前阶段(spec / coding / code_review / test / archive) |
64
+ | `phases.<phase>.status` | 阶段状态(pending / in_progress / completed) |
65
+ | `phases.<phase>.gates.<gate_name>.passed` | 门禁通过状态(null / true / false) |
66
+ | `phases.coding.tasks[]` | 编码任务列表(含 id / type / deps / batch / status / files) |
111
67
 
112
- ### Step 2: 启动 specline-spec-creator
68
+ > 📋 完整 JSON Schema 见 [附录 A](#附录-a-pipeline-statejson-完整-schema)
69
+
70
+ #### Step 2: 启动 specline-spec-creator
113
71
 
114
72
  specline-spec-creator 子 Agent 的职责是根据内联模板直接生成全部规划文件:
115
73
  - `proposal.md` — 需求提案(What/Why/Scope)
@@ -128,29 +86,30 @@ specline-spec-creator 子 Agent 的职责是根据内联模板直接生成全部
128
86
  > **注意**:specline-spec-creator 直接按内联模板生成 4 个 Artifact 并自检输出完整性(含并行度 ≥ 60% 和 Files 无冲突自检)。
129
87
 
130
88
  完成后写入状态:
89
+
131
90
  ```bash
132
91
  NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
133
92
  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"
134
93
  ```
135
94
 
136
- ### Step 3: 审核全部规划文件(specline-spec-reviewer)
95
+ #### Step 3: 审核全部规划文件(specline-spec-reviewer)
137
96
 
138
97
  specline-spec-reviewer 审核三份文件:
139
98
  1. `specs/` 下所有 spec.md 的完整性和一致性
140
- 2. `design.md` 的技术决策合理性和覆盖完整性(新增)
141
- 3. `tasks.md` 的格式、独立性、覆盖度、文件冲突(新增)
99
+ 2. `design.md` 的技术决策合理性和覆盖完整性
100
+ 3. `tasks.md` 的格式、独立性、覆盖度、文件冲突
142
101
 
143
102
  产出 spec-review.json (`{ "status": "approved"|"rejected", "feedback": [...], "coverage": {...}, "task_stats": {...} }`)。
144
103
 
145
104
  若 rejected:将 feedback 反馈给用户修改,或手动编辑相应文件后重新审核(最多 3 次循环)。
146
105
 
147
- ### Step 4: Spec Gate
106
+ #### Step 4: Spec Gate
148
107
 
149
108
  ```bash
150
109
  .cursor/hooks/specline-pipeline-gate.sh spec --change "<name>"
151
110
  ```
152
111
 
153
- 校验内容(在原有 spec.md 校验基础上增加):
112
+ 校验内容:
154
113
  - ✓ `proposal.md` 存在
155
114
  - ✓ `design.md` 存在
156
115
  - ✓ `tasks.md` 存在,且每个任务含 `Type:`、`Depends:`、`Covers:`、`Files:` 标注
@@ -160,10 +119,31 @@ specline-spec-reviewer 审核三份文件:
160
119
 
161
120
  exit code 0 = 通过,写入 passed。exit code != 0 = 失败,读取 stderr 展示给用户。
162
121
 
163
- ### Step 5: 人工确认 (Human Gate 1)
122
+ #### Step 5: 人工确认 (Human Gate 1) 🟡
164
123
 
165
124
  Spec Gate 通过后,使用 `AskUserQuestion` 工具请求确认。展示内容包括:需求提案摘要、功能需求列表、任务拆解概览(含并行组)。
166
125
 
126
+ > **用户交互规范**:所有需要用户做选择的交互,必须使用 `AskUserQuestion` 工具而非自由文本询问。结构化问题能让 Cursor 在单次请求中完成交互,避免额外轮次。
127
+
128
+ AskUserQuestion 使用模式:
129
+
130
+ ```javascript
131
+ AskUserQuestion({
132
+ title: "简洁标题",
133
+ questions: [{
134
+ id: "unique_id",
135
+ prompt: "问题描述",
136
+ options: [
137
+ { id: "option_a", label: "选项 A 的描述" },
138
+ { id: "option_b", label: "选项 B 的描述" }
139
+ ],
140
+ allow_multiple: false // 单选;需要多选时设为 true
141
+ }]
142
+ })
143
+ ```
144
+
145
+ Human Gate 1 具体交互:
146
+
167
147
  ```javascript
168
148
  AskUserQuestion({
169
149
  title: "确认 Spec 和任务规划",
@@ -184,11 +164,27 @@ AskUserQuestion({
184
164
  - `approve` → 写入 `human_gate_1.passed = true`,进入 Phase 2
185
165
  - `reject` → 等待用户修改 spec/tasks 文件后,回到 Step 3 重新审核
186
166
 
187
- ## Phase 2: CODING 阶段
167
+ ### Phase 2: CODING
188
168
 
189
169
  > **并行加速**:Human Gate 1 通过后,**同时**启动 coding 和 specline-test-writer。specline-test-writer 是黑盒的——只需要 Spec 文档,不需要实现代码。两者并行可节省 specline-test-writer 的编写时间。
190
170
 
191
- ### Step 6: 并行启动 specline-test-writer(与 Coding 并发)
171
+ #### Step 6: 并行启动(test-writer + DAG 构建)
172
+
173
+ 时序图:
174
+
175
+ ```
176
+ 时间 ────────────────────────────────────────────────────────────────────→
177
+
178
+ Track A (test-writer):
179
+ 6a 启动 ───── specline-test-writer(黑盒,与 Coding 并行运行) ──────→ 等待 Step 12
180
+
181
+ Track B (coding):
182
+ 6b 解析 tasks.md ──→ 6c 冲突检测 ──→ 7a 派发批次1 ──→ 7b 更新状态 ──→ 7c 派发批次2...
183
+
184
+ Step 8: Build Gate
185
+
186
+ Track A 和 Track B 同时启动,互不阻塞。test-writer 在 Coding 全部完成后、TEST 阶段前被检查(Step 12)。
187
+ ```
192
188
 
193
189
  **6a. 启动 specline-test-writer(与 Coding 阶段 Agent 同时启动)**:
194
190
 
@@ -211,13 +207,11 @@ Task({
211
207
  4. 基于 Covers 追溯链,确保每个 Scenario 都有测试
212
208
 
213
209
  ## 产出报告
214
- 完成后在 .cursor/tmp/test-code-result.json 写入状态(含 test_framework / language / test_dir / scenarios_covered 等字段)
210
+ 完成后在 specline/changes/${changeName}/.tmp/test-code-result.json 写入状态(含 test_framework / language / test_dir / scenarios_covered 等字段)
215
211
  `
216
212
  })
217
213
  ```
218
214
 
219
- specline-test-writer 在 Coding 阶段并行执行,不阻塞 coding agent 的派发。只有当 Coding 全部完成进入 TEST 阶段时,才需要等待 specline-test-writer 完成。
220
-
221
215
  **6b. 解析 tasks.md,构建任务 DAG**:
222
216
 
223
217
  读取 `specline/changes/<name>/tasks.md`,解析每个任务的 `Type`、`Depends`、`Covers`、`Files` 标注,构建依赖关系图,划分为多个**并行批次**。
@@ -247,7 +241,7 @@ jq --argjson tasks '[
247
241
  - 批次 1:所有 `Depends: (none)` 的任务
248
242
  - 批次 N:所有依赖仅限于 1..N-1 批次内已完成任务的任务
249
243
 
250
- ### Step 6c: 文件冲突检测(每批次派发前)
244
+ **6c. 文件冲突检测(每批次派发前)**:
251
245
 
252
246
  在派发每批任务之前,检查该批次中所有任务的 `Files` 集合是否有交集:
253
247
 
@@ -257,12 +251,7 @@ jq --argjson tasks '[
257
251
  # 如果有任意两个任务的 files 有交集 → 标记冲突任务对,暂停并报告用户
258
252
  ```
259
253
 
260
- 如果检测到文件冲突:
261
- 1. 标记冲突的任务为 `status: "conflict"`
262
- 2. 暂停流水线,告知用户哪两个任务的文件范围重叠
263
- 3. 用户可以手动调整 tasks.md 后恢复
264
-
265
- ### Step 7: 按批次并发派发 Coding Agent
254
+ #### Step 7: 按批次并发派发 Coding Agent
266
255
 
267
256
  对每个批次依次处理:
268
257
 
@@ -273,22 +262,25 @@ Type: frontend → subagent_type: "specline-frontend-dev"
273
262
  Type: backend → subagent_type: "specline-backend-dev"
274
263
  Type: infra → subagent_type: "specline-backend-dev"(基础设施类,用后端 agent 处理)
275
264
  Type: db → subagent_type: "specline-backend-dev"(数据库迁移,用后端 agent 处理)
276
- Type: config → 编排者直接处理(简单的文件创建/修改,不启动 agent
277
- Type: docs → 编排者直接处理(文档编写,不启动 agent)
265
+ Type: config → subagent_type: "specline-config-dev"(shell 脚本、配置文件、JSON/YAML
266
+ Type: docs → subagent_type: "specline-config-dev"(Markdown 文档、Skill 定义)
278
267
  ```
279
268
 
280
269
  每个任务启动一个独立的子 Agent:
281
270
 
282
271
  ```javascript
283
272
  for (const task of currentBatchTasks) {
284
- if (task.type === "config" || task.type === "docs") {
285
- // 简单文件操作,编排者直接写入
286
- // 不启动 agent,节省资源
287
- continue;
273
+ // 根据 Type 选择对应的 agent 类型
274
+ let agentType;
275
+ switch (task.type) {
276
+ case "frontend": agentType = "specline-frontend-dev"; break;
277
+ case "backend": case "infra": case "db": agentType = "specline-backend-dev"; break;
278
+ case "config": case "docs": agentType = "specline-config-dev"; break;
279
+ default: agentType = "specline-backend-dev";
288
280
  }
289
281
 
290
282
  Task({
291
- subagent_type: task.type === "frontend" ? "specline-frontend-dev" : "specline-backend-dev",
283
+ subagent_type: agentType,
292
284
  description: `实现任务 ${task.id}: ${task.title} [${task.type}]`,
293
285
  prompt: `
294
286
  你收到一个编码任务(Type: ${task.type}),请只实现本任务范围内的代码。
@@ -313,10 +305,10 @@ ${task.content}
313
305
  2. 不修改其他任务负责的文件
314
306
  3. 与已完成任务的接口约定必须遵守(参考已生成的接口/类型定义文件)
315
307
  4. 确认过 design.md 中的技术决策后再动手
316
- 5. **完成后必须将 tasks.md 中本任务的 `[ ]` 改为 `[x]`**(方便断点续跑识别进度)
308
+ 5. **完成后必须将 tasks.md 中本任务的 \`[ ]\` 改为 \`[x]\`**(方便断点续跑识别进度)
317
309
 
318
310
  ## 产出报告
319
- 完成后在 .cursor/tmp/task-${task.id}-result.json 写入:
311
+ 完成后在 specline/changes/${changeName}/.tmp/task-${task.id}-result.json 写入:
320
312
  {
321
313
  "task_id": "${task.id}",
322
314
  "type": "${task.type}",
@@ -331,7 +323,7 @@ ${task.content}
331
323
  ```
332
324
 
333
325
  **7b. 等待当前批次所有 Agent 完成后**:
334
- 1. 验证每个 Agent 的产出报告(`.cursor/tmp/task-<id>-result.json`)
326
+ 1. 验证每个 Agent 的产出报告(`specline/changes/<name>/.tmp/task-<id>-result.json`)
335
327
  2. 更新状态文件中对应 task 的 `status` 和 `completed_at`
336
328
  3. **验证 tasks.md 中对应任务的 checkbox 已从 `[ ]` 变为 `[x]`**(如果未标记,自动补标)
337
329
 
@@ -350,7 +342,7 @@ sed -i '' "s/^## ${task_id}\. \[ \]/## ${task_id}. [x]/" specline/changes/<name>
350
342
 
351
343
  **7c. 检查是否有下一批次**。如有,回到 6c(冲突检测)→ 7a 继续派发。
352
344
 
353
- ### Step 8: Build Gate
345
+ #### Step 8: Build Gate
354
346
 
355
347
  全部批次完成后,运行 Build Gate:
356
348
 
@@ -358,50 +350,25 @@ sed -i '' "s/^## ${task_id}\. \[ \]/## ${task_id}. [x]/" specline/changes/<name>
358
350
  .cursor/hooks/specline-pipeline-gate.sh build --change "<name>"
359
351
  ```
360
352
 
361
- 失败 分析失败原因,定位到具体任务:
353
+ exit code 0 = 通过,进入 Phase 3。失败处理见 [Layer 3: Build Gate 失败处理](#build-gate-失败处理)。
362
354
 
363
- **8a. 单个任务构建失败** 回对应 coding agent 修复(最多 2 次循环)
355
+ ### Phase 3: CODE REVIEW
364
356
 
365
- **8b. 接口不兼容** 计算影响范围,只重置受影响的下游任务:
357
+ #### Step 9: 启动审查 Agent
366
358
 
367
- ```bash
368
- # 影响范围分析:基于 tasks.md 的 Depends 关系,计算受影响的下游任务
369
- # 例如:Task 1 的 API 签名改了 → Task 3 (Depends: 1)、Task 5 (Depends: 1,3) 需要重跑
370
- # Task 2 无依赖关系 → 不受影响,保持 completed
359
+ 根据 tasks.md 中任务类型决定审查方式:
371
360
 
372
- AFFECTED_TASK_IDS=("3" "5") # DAG 计算得出
361
+ **9a. specline-code-reviewer**(有 frontend/backend/infra/db 类型任务时):
373
362
 
374
- for tid in "${AFFECTED_TASK_IDS[@]}"; do
375
- jq --arg tid "$tid" '
376
- .phases.coding.tasks |= map(
377
- if .id == $tid then .status = "pending" | .completed_at = null else . end
378
- )
379
- ' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
380
- done
381
- ```
382
-
383
- 影响范围算法:
384
- 1. 找到被修改的任务 ID 集合 M
385
- 2. 遍历所有任务,如果某任务的 Depends 列表中包含 M 中任一 ID,则加入受影响集合
386
- 3. 递归执行第 2 步直到不再扩展
387
-
388
- **8c. Build Gate 重置**:
389
-
390
- ```bash
391
- jq '.phases.coding.gates.build_gate.passed = null' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
392
- ```
363
+ 审查前端/后端代码变更。审查时利用 tasks.md `Covers` 追溯链:每个 finding 应标注涉及的文件和对应的 Requirement/Scenario。
393
364
 
394
- 修复后**只重跑受影响的任务**(按原批次顺序),未受影响的任务保持 completed 状态。
395
-
396
- ## Phase 3: CODE REVIEW 阶段
365
+ **9b. specline-config-reviewer**(有 config/docs 类型任务时):
397
366
 
398
- ### Step 9: 启动 specline-code-reviewer
367
+ 审查 config/docs 变更——shell 脚本安全性、配置文件语法和一致性、Markdown 文档结构完整性。
399
368
 
400
- specline-code-reviewer 审查代码变更。审查时利用 tasks.md `Covers` 追溯链:每个 finding 应标注涉及的文件和对应的 Requirement/Scenario。
369
+ > 两种审查 Agent 可并发启动。产出均为 `specline/changes/<name>/.tmp/code-review.json`(`{ "findings": [{ "severity": "error"|"warning", "file": "...", "covers": "Requirement: xxx", "message": "..." }] }`)。
401
370
 
402
- 产出 code-review.json (`{ "findings": [{ "severity": "error"|"warning", "file": "...", "covers": "Requirement: xxx", "message": "..." }] }`)。
403
-
404
- ### Step 10: Lint Gate
371
+ #### Step 10: Lint Gate
405
372
 
406
373
  ```bash
407
374
  .cursor/hooks/specline-pipeline-gate.sh lint --change "<name>"
@@ -411,7 +378,7 @@ specline-code-reviewer 审查代码变更。审查时利用 tasks.md 的 `Covers
411
378
 
412
379
  失败 → 根据 findings 的 `file` 和 `covers` 字段定位到具体任务,只回对应 coding agent 修复(最多 2 次)。
413
380
 
414
- ### Step 11: 可选人工复核 (Human Gate 2)
381
+ #### Step 11: 可选人工复核 (Human Gate 2) 🟡
415
382
 
416
383
  仅当 code-review.json 中 warnings > 0 且 errors = 0 时,使用 `AskUserQuestion`:
417
384
 
@@ -432,15 +399,17 @@ AskUserQuestion({
432
399
  - `skip`(默认)→ 自动继续
433
400
  - `review` → 展示警告详情,等待人工处理
434
401
 
435
- ## Phase 4: TEST 阶段
402
+ ### Phase 4: TEST
403
+
404
+ > **config/docs 跳过测试**:如果 tasks.md 中所有任务均为 `Type: config` 或 `Type: docs`(无应用代码变更),TEST 阶段自动跳过——test-unit/integration/e2e Gate 在无测试目录时自动放行。流水线直接从 CODE REVIEW 进入 ARCHIVE。
436
405
 
437
- ### Step 12: 确认 specline-test-writer 完成
406
+ #### Step 12: 确认 specline-test-writer 完成
438
407
 
439
408
  specline-test-writer 已在 Phase 2(Step 6a)与 Coding 并行启动。进入 TEST 阶段时,检查 specline-test-writer 是否已完成:
440
409
 
441
- - 已完成 → 读取 `.cursor/tmp/test-code-result.json` 获取 `test_framework`,写入 `.pipeline-state.json`:
410
+ - 已完成 → 读取 `specline/changes/<name>/.tmp/test-code-result.json` 获取 `test_framework`,写入 `.pipeline-state.json`:
442
411
  ```bash
443
- FRAMEWORK=$(jq -r '.test_framework' .cursor/tmp/test-code-result.json)
412
+ FRAMEWORK=$(jq -r '.test_framework' specline/changes/<name>/.tmp/test-code-result.json)
444
413
  jq --arg fw "$FRAMEWORK" '.phases.test.framework = $fw' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
445
414
  ```
446
415
  然后直接进入测试执行
@@ -450,7 +419,7 @@ specline-test-writer 已在 Phase 2(Step 6a)与 Coding 并行启动。进入
450
419
 
451
420
  > **黑盒约束回顾**:specline-test-writer 只能基于 Spec 文档编写测试,不能读取任何实现源代码。specline-test-writer 会自动检测项目测试框架(Jest/pytest/go test 等),按项目实际语言编写测试。
452
421
 
453
- ### Step 13: 测试门禁链(串行)
422
+ #### Step 13: 测试门禁链(串行)
454
423
 
455
424
  ```bash
456
425
  # 单元测试
@@ -461,24 +430,11 @@ specline-test-writer 已在 Phase 2(Step 6a)与 Coding 并行启动。进入
461
430
  .cursor/hooks/specline-pipeline-gate.sh test-e2e --change "<name>"
462
431
  ```
463
432
 
464
- 任何测试失败 specline-test-runner 分析原因:
465
- - 测试代码问题 → specline-test-writer 自修(最多 2 次)
466
- - 实现代码问题 → 利用 `Covers` 追溯链定位到具体任务,只回对应 coding agent 修复 → **使用影响范围算法精确重置受影响任务的 Gate**
467
- - `spec_ambiguity`(Spec 模糊)→ **不自动循环修复**,暂停流水线并展示模糊点给用户,等待用户澄清 Spec 后继续
468
- - 循环最多 2 次
469
-
470
- 代码修复后 Gate 重置:
471
- ```bash
472
- jq '
473
- .phases.test.sub_phases.unit.gates.test_unit_gate.passed = null |
474
- .phases.test.sub_phases.integration.gates.test_integration_gate.passed = null |
475
- .phases.test.sub_phases.e2e.gates.test_e2e_gate.passed = null
476
- ' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
477
- ```
433
+ exit code 0 = 通过,进入 Phase 5。失败处理见 [Layer 3: 测试失败处理](#测试失败处理)。
478
434
 
479
- ## Phase 5: ARCHIVE 阶段
435
+ ### Phase 5: ARCHIVE
480
436
 
481
- ### Step 14: 归档确认 (Human Gate 3)
437
+ #### Step 14: 归档确认 (Human Gate 3) 🟡
482
438
 
483
439
  全部测试通过后,使用 `AskUserQuestion` 请求归档确认:
484
440
 
@@ -496,21 +452,128 @@ AskUserQuestion({
496
452
  })
497
453
  ```
498
454
 
499
- - `archive` → 执行 specline-pipeline-gate.sh archive --execute --change
455
+ - `archive` → 执行归档
500
456
  - `cancel` → 暂停流水线,保留状态文件待后续继续
501
457
 
502
- ### Step 15: 归档
458
+ #### Step 15: 归档
503
459
 
504
460
  ```bash
505
461
  specline-pipeline-gate.sh archive --execute --change "<name>"
506
462
  .cursor/hooks/specline-pipeline-gate.sh archive --change "<name>"
507
463
  ```
508
464
 
465
+ > 归档的详细逻辑(Delta spec sync 决策、目录移动、摘要展示)由 **specline-archive-change** Skill 负责。编排者只需确认 Human Gate 3 通过后调用上述归档命令。
466
+
509
467
  ---
510
468
 
511
- ## 断点续跑流程
469
+ ## Layer 3: 异常与恢复
470
+
471
+ ### Build Gate 失败处理
472
+
473
+ ⚠️ Build Gate 失败时,分析失败原因并定位到具体任务:
474
+
475
+ **8a. 单个任务构建失败** → 回对应 coding agent 修复(最多 2 次循环)
476
+
477
+ **8b. 接口不兼容** → 计算影响范围,只重置受影响的下游任务:
512
478
 
513
- ### 发现未完成流水线
479
+ ```bash
480
+ # 影响范围分析:基于 tasks.md 的 Depends 关系,计算受影响的下游任务
481
+ # 例如:Task 1 的 API 签名改了 → Task 3 (Depends: 1)、Task 5 (Depends: 1,3) 需要重跑
482
+ # Task 2 无依赖关系 → 不受影响,保持 completed
483
+
484
+ AFFECTED_TASK_IDS=("3" "5") # 从 DAG 计算得出
485
+
486
+ for tid in "${AFFECTED_TASK_IDS[@]}"; do
487
+ jq --arg tid "$tid" '
488
+ .phases.coding.tasks |= map(
489
+ if .id == $tid then .status = "pending" | .completed_at = null else . end
490
+ )
491
+ ' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
492
+ done
493
+ ```
494
+
495
+ 影响范围算法:
496
+ 1. 找到被修改的任务 ID 集合 M
497
+ 2. 遍历所有任务,如果某任务的 Depends 列表中包含 M 中任一 ID,则加入受影响集合
498
+ 3. 递归执行第 2 步直到不再扩展
499
+
500
+ **8c. Build Gate 重置**:
501
+
502
+ ```bash
503
+ jq '.phases.coding.gates.build_gate.passed = null' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
504
+ ```
505
+
506
+ 修复后**只重跑受影响的任务**(按原批次顺序),未受影响的任务保持 completed 状态。
507
+
508
+ ### 测试失败处理
509
+
510
+ ⚠️ 任何测试失败 → specline-test-runner 分析原因:
511
+ - **测试代码问题** → specline-test-writer 自修(最多 2 次)
512
+ - **实现代码问题** → 利用 `Covers` 追溯链定位到具体任务,只回对应 coding agent 修复 → **使用影响范围算法精确重置受影响任务的 Gate**
513
+ - **`spec_ambiguity`**(Spec 模糊)→ **不自动循环修复**,暂停流水线并展示模糊点给用户,等待用户澄清 Spec 后继续
514
+ - 循环最多 2 次
515
+
516
+ 代码修复后 Gate 重置:
517
+
518
+ ```bash
519
+ jq '
520
+ .phases.test.sub_phases.unit.gates.test_unit_gate.passed = null |
521
+ .phases.test.sub_phases.integration.gates.test_integration_gate.passed = null |
522
+ .phases.test.sub_phases.e2e.gates.test_e2e_gate.passed = null
523
+ ' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
524
+ ```
525
+
526
+ ### Hook 阻断处理规范
527
+
528
+ ⚠️ 当任何子 Agent 被 `subagentStart` hook 阻止时,**编排者绝对不允许静默降级为自己直接执行**。必须按以下流程处理:
529
+
530
+ **Step 1: 识别阻断原因**
531
+
532
+ 根据阻断信息判断原因类型,按优先级诊断:
533
+
534
+ | 原因类型 | 典型症状 | 诊断命令 |
535
+ |---------|---------|---------|
536
+ | 脚本缺少执行权限 | "Permission denied" 或脚本执行失败 | `ls -la .cursor/hooks/specline-agent-guard.sh` |
537
+ | `jq` 未安装 | jq 相关错误 | `which jq` |
538
+ | Agent 名称不在白名单 | "子Agent类型 'xxx' 不在允许列表中" | 检查 `specline-agent-guard.sh` 中 `ALLOWED_AGENTS` 变量 |
539
+ | hooks.json 缺失或不完整 | hook 未触发或配置错误 | 检查 `.cursor/hooks.json` 文件是否存在且内容完整 |
540
+
541
+ **Step 2: 与用户沟通**
542
+
543
+ ```javascript
544
+ AskUserQuestion({
545
+ title: "Hook 阻断 - 子 Agent 启动失败",
546
+ questions: [{
547
+ id: "hook_fix",
548
+ prompt: `子 Agent **${agentName}** 被 hook 阻止,诊断结果:
549
+
550
+ **阻断原因**:${diagnosis}
551
+ **影响**:${impact_description}
552
+
553
+ **建议修复操作**:${fix_commands}
554
+
555
+ 请选择处理方式:`,
556
+ options: [
557
+ { id: "auto_fix", label: "自动修复(执行上述修复命令)" },
558
+ { id: "manual_fix", label: "我手动修复后通知你重试" },
559
+ { id: "skip_agent", label: "跳过此 Agent,由编排者直接执行(不推荐)" }
560
+ ]
561
+ }]
562
+ })
563
+ ```
564
+
565
+ **Step 3: 执行修复并重试**
566
+ - `auto_fix` → 执行修复命令(如 `chmod +x .cursor/hooks/*.sh`、安装 `jq` 等),修复完成后立即重试启动子 Agent
567
+ - `manual_fix` → 等待用户确认修复完成,然后重试启动子 Agent
568
+ - `skip_agent` → **仅当用户明确选择时才降级为编排者直接执行**,并必须在事件日志中记录降级原因
569
+
570
+ **Step 4: 验证修复结果** — 修复后重新启动子 Agent,如果仍然被阻止:重新诊断 → 再次沟通(最多循环 2 次)→ 暂停流水线并报告用户,不得自行降级
571
+
572
+ 此规范适用于**所有 hook 阻断场景**(`subagentStart`、`beforeShellExecution` 等)。
573
+
574
+ ### 断点续跑流程
575
+
576
+ #### 发现未完成流水线
514
577
 
515
578
  扫描 `specline/changes/*/.pipeline-state.json`:
516
579
 
@@ -545,13 +608,9 @@ AskUserQuestion({
545
608
  })
546
609
  ```
547
610
 
548
- 用户选择后:
549
- - 指定 change → 加载状态文件,计算恢复点
550
- - 无需再询问"是否继续",直接展示恢复摘要并自动开始恢复
611
+ #### 恢复算法
551
612
 
552
- ### 恢复算法
553
-
554
- 从后往前扫描 `phases` 中每个阶段的 `gates`,找到最后一个 `passed: true` 且 `run_at` 有值的门禁:
613
+ 从后往前扫描 `phases` 中每个阶段的 `gates`,找到最后一个 `passed: true` 的门禁:
555
614
 
556
615
  ```bash
557
616
  RESTORE_POINT="spec" # 默认从 spec 开始
@@ -573,7 +632,7 @@ for phase in archive test code_review coding spec; do
573
632
  done
574
633
  ```
575
634
 
576
- ### 重置不可信子阶段
635
+ #### 重置不可信子阶段
577
636
 
578
637
  ```bash
579
638
  # 将恢复阶段中 completed_at 为空的子阶段重置为 pending
@@ -588,7 +647,7 @@ jq --arg phase "$RESTORE_POINT" '
588
647
  ' "$STATE_FILE" > tmp && mv tmp "$STATE_FILE"
589
648
  ```
590
649
 
591
- ### 从 tasks.md 恢复已完成任务状态
650
+ #### 从 tasks.md 恢复已完成任务状态
592
651
 
593
652
  恢复到 CODING 阶段时,必须先读取 tasks.md 的 checkbox 状态,与 `.pipeline-state.json` 交叉校验:
594
653
 
@@ -609,7 +668,7 @@ done
609
668
 
610
669
  这个交叉校验确保:即使 `.pipeline-state.json` 丢失或损坏,tasks.md 的 `[x]`/`[ ]` 标记仍可作为任务进度的可靠来源。
611
670
 
612
- ### 展示恢复摘要
671
+ #### 展示恢复摘要
613
672
 
614
673
  计算恢复点后,**直接开始恢复,不需要再次人工确认**(用户选择 pipeline 时已确认意图)。
615
674
 
@@ -629,7 +688,35 @@ AskUserQuestion({
629
688
  })
630
689
  ```
631
690
 
632
- ## 状态写入规则
691
+ ---
692
+
693
+ ## Layer 4: 附录
694
+
695
+ > ℹ️ 初次阅读可跳过 — 以下为完整参考信息,首次阅读可略过
696
+
697
+ ### 附录 A: .pipeline-state.json 完整 Schema
698
+
699
+ ```json
700
+ {
701
+ "version": 1,
702
+ "change_name": "<name>",
703
+ "created_at": "<ISO8601>",
704
+ "updated_at": "<ISO8601>",
705
+ "current_phase": "spec",
706
+ "current_step": "specline-spec-creator",
707
+ "phases": {
708
+ "spec": { "status": "in_progress", "retry_count": 0, "sub_phases": {}, "gates": { "spec_gate": { "passed": null }, "human_gate_1": { "passed": null } } },
709
+ "coding": { "status": "pending", "tasks": [], "sub_phases": {}, "gates": { "build_gate": { "passed": null } } },
710
+ "code_review": { "status": "pending", "retry_count": 0, "gates": { "lint_gate": { "passed": null }, "human_gate_2": { "passed": null } } },
711
+ "test": { "status": "pending", "framework": null, "sub_phases": { "unit": { "status": "pending", "gates": { "test_unit_gate": { "passed": null } } }, "integration": { "status": "pending", "gates": { "test_integration_gate": { "passed": null } } }, "e2e": { "status": "pending", "gates": { "test_e2e_gate": { "passed": null } } } } },
712
+ "archive": { "status": "pending", "gates": { "human_gate_3": { "passed": null }, "archive_gate": { "passed": null } } }
713
+ }
714
+ }
715
+ ```
716
+
717
+ ### 附录 B: 状态写入规则
718
+
719
+ > ℹ️ 初次阅读可跳过
633
720
 
634
721
  所有状态写入由 Gate 脚本或 Skill 编排逻辑完成,**不使用 LLM 写入状态**:
635
722
 
@@ -637,11 +724,11 @@ AskUserQuestion({
637
724
  - 子 Agent 完成后 Skill 写入 `completed_at`
638
725
  - 代码修复后 Skill 重置相关 gates 为 null
639
726
 
640
- ## 结构化事件日志(可观测性)
727
+ ### 附录 C: 结构化事件日志
641
728
 
642
- 每个关键事件追加写入 `specline/changes/<name>/pipeline-events.jsonl`(JSON Lines 格式,每行一个事件):
729
+ > ℹ️ 初次阅读可跳过
643
730
 
644
- 日志事件类型:
731
+ 每个关键事件追加写入 `specline/changes/<name>/pipeline-events.jsonl`(JSON Lines 格式,每行一个事件):
645
732
 
646
733
  ```json
647
734
  {"ts":"...","event":"pipeline_start","change":"<name>"}
@@ -665,10 +752,50 @@ AskUserQuestion({
665
752
  - Gate 脚本不写事件日志(Gate 是无状态的),仅编排层写入
666
753
  - 事件日志用于人工排查问题和统计分析,不影响流水线决策
667
754
 
668
- ## 关键约束
755
+ ### 附录 D: Hook 约束体系
756
+
757
+ > ℹ️ 初次阅读可跳过
758
+
759
+ Specline 通过 Cursor Hooks 提供了三层自动约束,确保在长对话中 Agent 不偏离流水线逻辑:
760
+
761
+ ```
762
+ sessionStart → specline-session-start.sh
763
+ 新会话启动时检测活跃 pipeline,自动注入阶段上下文到 Agent 系统提示
764
+
765
+ preToolUse → specline-phase-guard.sh
766
+ 操作前检查:SPEC 阶段拦截代码编辑、阶段不匹配的子Agent 启动
767
+
768
+ postToolUse → specline-reminder.sh
769
+ 关键操作后注入提醒:更新 tasks.md checkbox、运行 Gate 脚本
770
+ ```
771
+
772
+ #### 对你(编排者)的影响
773
+
774
+ 1. **总是先检查** - preToolUse 会阻止不匹配当前阶段的操作,所以你在行动前自然会考虑阶段
775
+ 2. **被提醒下一步** - postToolUse 在子Agent完成后提醒你更新 checkbox 和运行 Gate
776
+ 3. **非流水线会话无影响** - 所有 Hook 的第一步检查「是否有活跃 pipeline」,无则透明放行
777
+
778
+ #### 约束策略
779
+
780
+ | 场景 | 策略 | 原因 |
781
+ |------|------|------|
782
+ | SPEC 阶段编辑代码文件 | **硬拦截 (deny)** | 明确违规 |
783
+ | SPEC 阶段启动编码 Agent | **硬拦截 (deny)** | 阶段不匹配 |
784
+ | CODING 阶段直接编辑代码 | **软提醒 (postToolUse)** | Hook 无法区分编排者和子Agent的 Write |
785
+ | 子Agent完成后忘记 Gate | **软提醒 (postToolUse)** | 操作后注入下一步提醒 |
786
+
787
+ > 注意:CODING 阶段 Orchestrator 直接编辑代码文件不会被 Hook 硬拦截(因为子Agent 也需要 Write 权限),但 SKILL 指令和 sessionStart 注入的上下文会持续提醒你「编码应通过子 Agent」。如果你发现自己想直接编辑代码,停一下,改用 Task 工具。
788
+
789
+ ### 附录 E: 关键约束速查表
790
+
791
+ > ℹ️ 初次阅读可跳过
669
792
 
670
- 1. **不做判断,只做编排**:不要评估代码质量、需求好坏、测试覆盖——这些由子 Agent Gate 脚本负责
671
- 2. **所有门禁通过 `specline-pipeline-gate.sh` 执行**:不要自己写 grep/检查逻辑,调用脚本即可
672
- 3. **状态文件是唯一真相源**:所有决策基于 `.pipeline-state.json` 的当前值
673
- 4. **人工确认点必须暂停**:不要自动跳过 human_gate
674
- 5. **测试 Agent 必须黑盒**:不给 specline-test-writer 传递源代码文件路径
793
+ | # | 约束 | 说明 |
794
+ |---|------|------|
795
+ | 1 | **不做判断,只做编排** | 不评估代码质量、需求好坏、测试覆盖——这些由子 Agent 和 Gate 脚本负责 |
796
+ | 2 | **所有门禁通过 Gate 脚本** | 调用 `specline-pipeline-gate.sh`,不要自己写 grep/检查逻辑 |
797
+ | 3 | **状态文件是唯一真相源** | 所有决策基于 `.pipeline-state.json` 的当前值 |
798
+ | 4 | **人工确认点必须暂停** | 不要自动跳过 human_gate |
799
+ | 5 | **测试 Agent 必须黑盒** | 不给 specline-test-writer 传递源代码文件路径 |
800
+ | 6 | **Hook 阻断绝不静默降级** | 子 Agent 被 hook 阻止时,必须先诊断、沟通、修复后重试 |
801
+ | 7 | **接受 Hook 约束** | preToolUse/postToolUse/sessionStart Hook 会自动校验和提醒,不要试图绕过 |