@boyingliu01/opencode-plugin 0.12.14 → 0.13.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/package.json +1 -1
- package/skills/delphi-review/AGENTS.md +4 -4
- package/skills/sprint-flow/AGENTS.md +50 -62
- package/skills/sprint-flow/SKILL.md +200 -238
- package/skills/sprint-flow/references/force-levels.md +13 -14
- package/skills/sprint-flow/references/orchestration-rules.md +61 -197
- package/skills/sprint-flow/references/phase-1-prep.md +294 -0
- package/skills/sprint-flow/references/phase-2-design.md +194 -0
- package/skills/sprint-flow/references/{phase-2-build.md → phase-3-build.md} +11 -11
- package/skills/sprint-flow/references/phase-4-verify.md +153 -0
- package/skills/sprint-flow/references/phase-5-ship.md +40 -0
- package/skills/sprint-flow/references/phase-6-close.md +134 -0
- package/skills/sprint-flow/templates/auto-estimate-learning-log.md +1 -1
- package/skills/sprint-flow/templates/auto-estimate-output-template.md +15 -37
- package/skills/sprint-flow/templates/emergent-issues-template.md +7 -7
- package/skills/sprint-flow/templates/pain-document-template.md +5 -5
- package/skills/sprint-flow/templates/sprint-progress-template.md +36 -47
- package/skills/sprint-flow/templates/sprint-summary-template.md +16 -15
- package/skills/test-specification-alignment/AGENTS.md +4 -4
- package/skills/sprint-flow/references/phase-0-think.md +0 -115
- package/skills/sprint-flow/references/phase-1-plan.md +0 -178
- package/skills/sprint-flow/references/phase-3-review.md +0 -215
- package/skills/sprint-flow/references/phase-4-uat.md +0 -125
- package/skills/sprint-flow/references/phase-5-feedback.md +0 -100
- package/skills/sprint-flow/references/phase-6-ship.md +0 -9
- package/skills/sprint-flow/references/phase-7-land.md +0 -9
- package/skills/sprint-flow/references/phase-8-cleanup.md +0 -9
- package/skills/sprint-flow/references/phase-minus-0-5-auto-estimate.md +0 -263
- package/skills/sprint-flow/references/phase-minus-1-isolate.md +0 -58
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Sprint Flow 执行级别定义
|
|
2
2
|
|
|
3
|
-
**执行时机**: Phase
|
|
3
|
+
**执行时机**: Phase 2/6 DESIGN 之前,PREP AUTO-ESTIMATE 完成后。
|
|
4
4
|
|
|
5
5
|
**目的**: 根据需求规模匹配适度评审流程,平衡质量保障与效率。
|
|
6
6
|
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
|
|
74
74
|
## 与 AUTO-ESTIMATE 的关系
|
|
75
75
|
|
|
76
|
-
AUTO-ESTIMATE
|
|
76
|
+
AUTO-ESTIMATE 提供**初始级别建议**(Phase 1/6 PREP),Force Levels 定义**具体执行规则**:
|
|
77
77
|
|
|
78
78
|
```
|
|
79
79
|
AUTO-ESTIMATE 输出 → Force Levels 执行 → 自动升级机制(如触发)
|
|
@@ -94,19 +94,19 @@ AUTO-ESTIMATE 输出 → Force Levels 执行 → 自动升级机制(如触发
|
|
|
94
94
|
|
|
95
95
|
## 与 DELPHI-GATE 的关系
|
|
96
96
|
|
|
97
|
-
**DELPHI-GATE** 是 Phase
|
|
97
|
+
**DELPHI-GATE** 是 Phase 3/6 BUILD 的**强制门禁**,检查 `.sprint-state/delphi-reviewed.json` 的 `verdict=APPROVED`。Force Levels 定义**产生该门禁文件的评审强度**:
|
|
98
98
|
|
|
99
99
|
| 场景 | DELPHI-GATE | Force Levels |
|
|
100
100
|
|------|------------|-------------|
|
|
101
|
-
| Phase
|
|
102
|
-
| Phase
|
|
101
|
+
| Phase 2/6 DESIGN 设计评审 | 3 专家、≥90% 共识、生成 specification.yaml | 不适用(设计阶段) |
|
|
102
|
+
| Phase 3/6 BUILD 入口 | **必须检查** `.sprint-state/delphi-reviewed.json` 中 `verdict=APPROVED` | 轻量/标准/复杂:通过对应强度的 delphi-review 生成该门禁文件 |
|
|
103
103
|
| 轻量级评审 | 生成 `delphi-reviewed.json`(2 专家、1 轮、2/2 批准) | 2 专家、1 轮、写入门禁文件 |
|
|
104
104
|
| 标准级评审 | 生成 `delphi-reviewed.json`(2 专家、最多 2 轮、2/2 批准) | 2 专家、最多 2 轮、写入门禁文件 |
|
|
105
105
|
| 复杂级评审 | 生成 `delphi-reviewed.json`(3 专家、最多 3 轮、3/3 批准) | 3 专家、最多 3 轮、写入门禁文件 |
|
|
106
|
-
| Phase
|
|
106
|
+
| Phase 4/6 VERIFY 代码走查 | 再次检查 `delphi-reviewed.json` 或重新评审 | 复用 Force Levels 规则 |
|
|
107
107
|
|
|
108
108
|
**关键规则**:
|
|
109
|
-
- **DELPHI-GATE 永不跳过**:Phase
|
|
109
|
+
- **DELPHI-GATE 永不跳过**:Phase 3/6 BUILD 入口必须检查 `.sprint-state/delphi-reviewed.json` 中 `verdict=APPROVED`
|
|
110
110
|
- **Force Levels 定义评审强度**:轻量/标准/复杂决定用 2 专家 1 轮还是 3 专家 3 轮来**产生**门禁文件
|
|
111
111
|
- **轻量级不是跳过评审**:而是简化流程(2 专家、1 轮),但仍需生成门禁文件
|
|
112
112
|
- **LIGHTWEIGHT ≠ ONE-EXPERT**: 1 专家违反 Delphi 核心原则,禁止
|
|
@@ -189,15 +189,14 @@ AUTO-ESTIMATE 输出 → Force Levels 执行 → 自动升级机制(如触发
|
|
|
189
189
|
|
|
190
190
|
**仲裁机制**:
|
|
191
191
|
- Round 2 仍有分歧 → 第 3 专家(Qwen3.6-Plus)加入仲裁
|
|
192
|
-
- Round 3 必须达成一致,否则 BLOCK 进入 Phase
|
|
192
|
+
- Round 3 必须达成一致,否则 BLOCK 进入 Phase 3/6 BUILD
|
|
193
193
|
|
|
194
194
|
---
|
|
195
195
|
|
|
196
196
|
## 参见
|
|
197
197
|
|
|
198
|
-
- [Phase
|
|
199
|
-
- [Phase
|
|
200
|
-
- [Phase
|
|
201
|
-
- [Phase
|
|
202
|
-
- [
|
|
203
|
-
- [Delphi Review Skill](../../../../skills/delphi-review/SKILL.md) — 多专家共识评审规范
|
|
198
|
+
- [Phase 1/6: PREP](../references/phase-1-prep.md) — worktree 隔离 + 规模评估
|
|
199
|
+
- [Phase 2/6: DESIGN](../references/phase-2-design.md) — 需求探索 + 共识评审
|
|
200
|
+
- [Phase 3/6: BUILD](../references/phase-3-build.md) — TDD + raph-loop 构建
|
|
201
|
+
- [Phase 4/6: VERIFY](../references/phase-4-verify.md) — 代码走查 + 反馈
|
|
202
|
+
- [Delphi Review Skill](../../delphi-review/SKILL.md) — 多专家共识评审规范
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
- 3+ 个独立搜索角度
|
|
16
16
|
- 读取多个大文件(>200 行)
|
|
17
17
|
- 需要跨层分析(如"查 ralph-loop + .sprint-state/ + token 阈值 + phase transition")
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
→ **必须用 `task(category="deep", load_skills=[...])` 替代**
|
|
20
20
|
|
|
21
21
|
2. 如果 `explore` agent >5 分钟未返回 → cancel 并立即用 `task(category="deep")` 重试。不要等待。
|
|
@@ -28,35 +28,31 @@
|
|
|
28
28
|
|
|
29
29
|
| Phase | 名称 | Subagent? | Category | load_skills | 执行者 |
|
|
30
30
|
|-------|------|:---------:|----------|-------------|--------|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
| 4 | USER ACCEPT | ❌ | **强制人工** | 无 | 用户 |
|
|
38
|
-
| 5 | FEEDBACK | ✅ | `quick` | `["learn", "retro", "systematic-debugging"]` | subagent |
|
|
39
|
-
| 6 | SHIP | ❌ | orchestrator(直接执行) | `["finishing-a-development-branch", "ship"]` | orchestrator |
|
|
40
|
-
| 7 | LAND | ❌ | orchestrator(直接执行) | `["land-and-deploy"]` | orchestrator |
|
|
41
|
-
| 8 | CLEANUP | ❌ | Bash(直接执行) | 无 | orchestrator |
|
|
31
|
+
| 1/6 | PREP | ❌ | Bash(直接执行) | 无 | orchestrator |
|
|
32
|
+
| 2/6 | DESIGN | ❌ | orchestrator(直接执行) | `["brainstorming", "autoplan", "delphi-review", "to-issues"]` | orchestrator |
|
|
33
|
+
| 3/6 | BUILD | ✅ | ralph-loop | `["test-driven-development"]` | subagent |
|
|
34
|
+
| 4/6 | VERIFY | ❌ | orchestrator(直接执行) | `["delphi-review", "test-specification-alignment", "learn", "retro", "systematic-debugging"]` | orchestrator |
|
|
35
|
+
| 5/6 | SHIP | ❌ | orchestrator(直接执行) | `["finishing-a-development-branch", "ship", "land-and-deploy"]` | orchestrator |
|
|
36
|
+
| 6/6 | CLOSE | ❌ | **强制人工 (UAT)** + Bash (CLEANUP) | 无 | 用户 + orchestrator |
|
|
42
37
|
|
|
43
38
|
**⚠️ 交互式 skill 必须由 orchestrator 直接执行(不可 dispatch 到 subagent)**:
|
|
44
39
|
|
|
45
40
|
| Phase | Skill | 为什么不能在 subagent 中执行 |
|
|
46
41
|
|-------|-------|---------------------------|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
| 6 | `finishing-a-development-branch` | 4 选项菜单 (merge/PR/keep/discard) 需要用户选择;Option 4 (discard) 要求 typed confirmation |
|
|
53
|
-
| 6 | `ship` | PR 创建前需要用户确认;包含 AskUserQuestion STOP 点 |
|
|
54
|
-
|
|
|
55
|
-
|
|
56
|
-
**Phase
|
|
57
|
-
1. **Orchestrator 直接执行
|
|
58
|
-
2. **Orchestrator 直接执行
|
|
59
|
-
3. **Orchestrator 直接执行
|
|
42
|
+
| 2/6 | `brainstorming` | 需要与用户对话确认需求、提出澄清问题。Subagent 是 fire-and-forget 模式,无法暂停等待用户输入(Issue #217) |
|
|
43
|
+
| 2/6 | `autoplan` | taste_decisions 节点暂停等待用户确认。必须由 orchestrator 直接执行(Issue #225) |
|
|
44
|
+
| 2/6 | `delphi-review` | design 模式需等待 verdict APPROVED;非 APPROVED 时需用户确认是否接受分歧方案(Issue #249) |
|
|
45
|
+
| 2/6 | `to-issues` | Step 6 "向用户确认" — 展示拆分结果,等待用户批准后才生成 slices-manifest.json |
|
|
46
|
+
| 4/6 | `delphi-review --mode code-walkthrough` | Code walkthrough 非 APPROVED 时需暂停等待用户处理 Critical Issues(Issue #249) |
|
|
47
|
+
| 5/6 | `finishing-a-development-branch` | 4 选项菜单 (merge/PR/keep/discard) 需要用户选择;Option 4 (discard) 要求 typed confirmation |
|
|
48
|
+
| 5/6 | `ship` | PR 创建前需要用户确认;包含 AskUserQuestion STOP 点 |
|
|
49
|
+
| 5/6 | `land-and-deploy` | Merge 确认、rollback 决策 — 均为用户交互点 |
|
|
50
|
+
|
|
51
|
+
**Phase 2/6 DESIGN 执行模式(全部 orchestrator 直接执行)**:
|
|
52
|
+
1. **Orchestrator 直接执行 brainstorming**:`skill(name="brainstorming")` → 等待 APPROVED
|
|
53
|
+
2. **Orchestrator 直接执行 autoplan**:`skill(name="autoplan")` → 等待用户确认 taste_decisions
|
|
54
|
+
3. **Orchestrator 直接执行 delphi-review**:`skill(name="delphi-review")` → 等待 APPROVED
|
|
55
|
+
4. **Orchestrator 直接执行 to-issues**:`skill(name="to-issues")` → 等待用户确认 Issue 拆分
|
|
60
56
|
|
|
61
57
|
**上下文隔离原则**:
|
|
62
58
|
- 每个 Subagent 在**独立 session** 中启动,不继承 orchestrator 的对话历史
|
|
@@ -69,25 +65,21 @@
|
|
|
69
65
|
|
|
70
66
|
| Phase | 加载来源 | 内容 |
|
|
71
67
|
|-------|---------|------|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
| Phase 5 | phase-4-summary.md + emergent-issues.md | 验收结论 |
|
|
79
|
-
| Phase 6 | phase-5-summary.md + feedback-log.md | 复盘结论 |
|
|
80
|
-
| Phase 7 | phase-6-summary.md + PR URL | 发布准备 |
|
|
81
|
-
| Phase 8 | phase-7-summary(Bash 操作) | 部署结果 |
|
|
68
|
+
| 1/6 PREP | 无前置(Bash 操作) | 用户原始需求 + 当前分支状态 |
|
|
69
|
+
| 2/6 DESIGN | phase-1-summary(仅路径) | 隔离环境信息(worktree 路径) |
|
|
70
|
+
| 3/6 BUILD | phase-2-summary.md + specification.yaml + slices-manifest.json | 设计决策 + REQ 列表 |
|
|
71
|
+
| 4/6 VERIFY | phase-3-summary.md + MVP 代码 | 构建结果(orchestrator 直接执行) |
|
|
72
|
+
| 5/6 SHIP | phase-4-summary.md + feedback-log.md | 评审结论 + 复盘结论 |
|
|
73
|
+
| 6/6 CLOSE | phase-5-summary.md + PR URL | 发布准备 + 部署结果 |
|
|
82
74
|
|
|
83
75
|
**隔离原则**:每个 Phase subagent 在干净上下文中启动。
|
|
84
76
|
输入仅限上表对应的摘要文件和一级产出物。
|
|
85
77
|
不包含前一 Phase 的完整对话、中间文件、失败尝试。
|
|
86
78
|
|
|
87
79
|
**特殊场景**:
|
|
88
|
-
- `--resume-from <phase>`:跳过前置 Phase,直接从指定 Phase 启动。**MUST 先执行 RESUME GATE(Issue #148)** 校验 sprint 状态、git 可达性和文件时效性,再执行 Phase Transition Gate 校验摘要文件格式。例如 `--resume-from build` 要求 `phase-
|
|
89
|
-
- `--no-isolate`:跳过 Phase
|
|
90
|
-
- `next_phase_context` 中的 `{path}`
|
|
80
|
+
- `--resume-from <phase>`:跳过前置 Phase,直接从指定 Phase 启动。**MUST 先执行 RESUME GATE(Issue #148)** 校验 sprint 状态、git 可达性和文件时效性,再执行 Phase Transition Gate 校验摘要文件格式。例如 `--resume-from build` 要求 `phase-2-summary.md` 和 `specification.yaml` 已存在且非 stale。
|
|
81
|
+
- `--no-isolate`:跳过 Phase 1/6 PREP 的 worktree 隔离,直接在当前分支执行。Phase 2/6 DESIGN 无 `phase-1-summary` 可用,上下文继承来源为用户原始需求 + 当前 git 状态。所有后续 Phase 的 worktree enforcement 不适用(无 worktree),但仍需保持代码隔离。
|
|
82
|
+
- `next_phase_context` 中的 `{path}` 等变量占位符在实际写入时被替换为具体值。
|
|
91
83
|
|
|
92
84
|
### PHASE TRANSITION RULES
|
|
93
85
|
|
|
@@ -98,27 +90,27 @@
|
|
|
98
90
|
- 大小限制:≤ 40,000 字符(≈ 10,000 tokens)
|
|
99
91
|
|
|
100
92
|
2. **更新 sprint-state.json**:
|
|
101
|
-
- `phase`: 当前阶段编号
|
|
93
|
+
- `phase`: 当前阶段编号 (1-6)
|
|
102
94
|
- `outputs`: 新增当前阶段输出文件路径
|
|
103
95
|
- `phase_history`: 追加或更新当前阶段的记录
|
|
104
96
|
- Phase 开始时:追加 `{ "phase": N, "phase_name": "NAME", "status": "running", "started_at": "<ISO 8601>", "completed_at": null, "duration_seconds": null }`
|
|
105
|
-
- Phase 完成时:更新对应条目,填充 `completed_at`(ISO 8601)和 `duration_seconds
|
|
106
|
-
- Phase
|
|
97
|
+
- Phase 完成时:更新对应条目,填充 `completed_at`(ISO 8601)和 `duration_seconds`
|
|
98
|
+
- Phase 跳过时:设置 `status: "skipped"`
|
|
107
99
|
|
|
108
100
|
3. **等待用户确认 checkpoint**(如适用)
|
|
109
101
|
|
|
110
102
|
4. **展示进度看板**:执行 `node scripts/render-sprint-progress.cjs` 渲染进度看板
|
|
111
103
|
- 脚本自动读取 `.sprint-state/sprint-state.json` 并输出 ASCII 进度看板
|
|
112
104
|
- 渲染规则:已完成阶段显示 ✅ + 耗时,当前阶段 🔄,待做 ⬜,跳过 ⏭️,失败 ❌
|
|
113
|
-
- 进度条:`[████▓░░░░░░] {pct}%`(已完成数/总阶段数
|
|
105
|
+
- 进度条:`[████▓░░░░░░] {pct}%`(已完成数/总阶段数 6)
|
|
114
106
|
- 下一步行动:根据当前阶段 + 状态,自动查找对应提示
|
|
115
107
|
- 输出物路径:列出 `outputs` 中已有的文件路径
|
|
116
|
-
- 时机:每个 Phase 完成后的 transition
|
|
108
|
+
- 时机:每个 Phase 完成后的 transition 阶段自动展示
|
|
117
109
|
- 向后兼容:旧版 `sprint-state.json` 缺少 `phase_history` 时,从 `phase` 字段推断状态
|
|
118
110
|
|
|
119
111
|
### Background Task Resume Protocol (MANDATORY — Issue #248)
|
|
120
112
|
|
|
121
|
-
After dispatching background agents with `run_in_background=true
|
|
113
|
+
After dispatching background agents with `run_in_background=true`:
|
|
122
114
|
|
|
123
115
|
1. **END YOUR RESPONSE** — do NOT poll `background_output()` before receiving `<system-reminder>`
|
|
124
116
|
2. **On `<system-reminder>` notification**: collect ALL completed results via `background_output(task_id="bg_...")`
|
|
@@ -128,7 +120,7 @@ After dispatching background agents with `run_in_background=true` (e.g., Phase -
|
|
|
128
120
|
c. Continuing to the next phase **WITHOUT waiting for human input**
|
|
129
121
|
4. **If any task failed**: collect partial results, log the failure, continue with available data (do NOT block the pipeline)
|
|
130
122
|
|
|
131
|
-
**The orchestrator MUST treat task completion notifications as an implicit "continue" signal.** This protocol prevents the "human-in-loop stall"
|
|
123
|
+
**The orchestrator MUST treat task completion notifications as an implicit "continue" signal.** This protocol prevents the "human-in-loop stall" (Issue #235, #248).
|
|
132
124
|
|
|
133
125
|
### Phase Summary 格式(YAML Frontmatter Schema)
|
|
134
126
|
|
|
@@ -136,8 +128,8 @@ After dispatching background agents with `run_in_background=true` (e.g., Phase -
|
|
|
136
128
|
|
|
137
129
|
```markdown
|
|
138
130
|
---
|
|
139
|
-
phase:
|
|
140
|
-
phase_name:
|
|
131
|
+
phase: 1
|
|
132
|
+
phase_name: PREP
|
|
141
133
|
status: completed
|
|
142
134
|
outputs:
|
|
143
135
|
- path: ".worktrees/sprint/sprint-YYYY-MM-DD-NN"
|
|
@@ -148,165 +140,43 @@ decisions:
|
|
|
148
140
|
unresolved_issues: []
|
|
149
141
|
next_phase_context: "Worktree created at {path}. All subsequent edits MUST use this workdir."
|
|
150
142
|
---
|
|
151
|
-
|
|
152
|
-
## Phase Summary
|
|
153
|
-
{简明摘要,不超过 50 行}
|
|
154
143
|
```
|
|
155
144
|
|
|
156
145
|
**必填字段**: `phase`, `phase_name`, `status`, `outputs`, `decisions`, `next_phase_context`
|
|
157
|
-
**可选字段**: `unresolved_issues`
|
|
158
146
|
|
|
159
147
|
### Phase Transition Gate
|
|
160
148
|
|
|
161
|
-
Orchestrator dispatch 下一 Phase
|
|
149
|
+
Orchestrator dispatch 下一 Phase 前必须执行验证(与旧模型相同,但 phase number 使用 1-6):
|
|
162
150
|
|
|
163
151
|
```bash
|
|
164
|
-
# === Phase Transition Gate ===
|
|
165
|
-
|
|
166
|
-
# 1. Phase summary file validation
|
|
167
152
|
SUMMARY=".sprint-state/phase-outputs/phase-${N}-summary.md"
|
|
168
153
|
[ -f "$SUMMARY" ] || { echo "[BLOCK] phase-${N}-summary 不存在"; exit 1; }
|
|
169
|
-
|
|
170
|
-
[ "$FRONTMARKERS" -ge 2 ] || { echo "[BLOCK] YAML frontmatter 格式不完整"; exit 1; }
|
|
171
|
-
grep -q "^phase:" "$SUMMARY" || { echo "[BLOCK] 缺少 phase 字段"; exit 1; }
|
|
172
|
-
grep -q "^phase_name:" "$SUMMARY" || { echo "[BLOCK] 缺少 phase_name 字段"; exit 1; }
|
|
173
|
-
grep -q "^status:" "$SUMMARY" || { echo "[BLOCK] 缺少 status 字段"; exit 1; }
|
|
174
|
-
grep -q "^decisions:" "$SUMMARY" || { echo "[BLOCK] 缺少 decisions 字段"; exit 1; }
|
|
175
|
-
grep -q "^outputs:" "$SUMMARY" || { echo "[BLOCK] 缺少 outputs 字段"; exit 1; }
|
|
176
|
-
grep -q "^next_phase_context:" "$SUMMARY" || { echo "[BLOCK] 缺少 next_phase_context"; exit 1; }
|
|
177
|
-
CHARS=$(wc -c < "$SUMMARY" | tr -d ' ')
|
|
178
|
-
[ "$CHARS" -le 40000 ] || { echo "[BLOCK] 摘要超出大小限制 (${CHARS}/40000 chars)"; exit 1; }
|
|
179
|
-
|
|
180
|
-
# 2. sprint-state.json enforcement check (Issue #146)
|
|
181
|
-
SPRINT_STATE=".sprint-state/sprint-state.json"
|
|
182
|
-
[ -f "$SPRINT_STATE" ] || { echo "[BLOCK] sprint-state.json 不存在"; exit 1; }
|
|
183
|
-
|
|
184
|
-
# Verify phase_history includes current phase with completed_at
|
|
185
|
-
PHASE_HISTORY_CHECK=$(grep -c "\"phase\": $N" "$SPRINT_STATE" 2>/dev/null || echo 0)
|
|
186
|
-
[ "$PHASE_HISTORY_CHECK" -gt 0 ] || {
|
|
187
|
-
echo "[BLOCK] sprint-state.json phase_history 缺少 phase $N 的记录"
|
|
188
|
-
echo "[ACTION] 在 dispatch 下一 Phase 前更新 sprint-state.json:"
|
|
189
|
-
echo " - phase: $N"
|
|
190
|
-
echo " - phase_history: 追加 {phase:N, status:completed, completed_at:<ISO8601>}"
|
|
191
|
-
echo " - outputs: 追加当前 phase 的输出文件"
|
|
192
|
-
exit 1
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
# Verify completed_at is set (not null)
|
|
196
|
-
COMPLETED_AT_VALUE=$(grep -A3 "\"phase\": $N" "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | grep -o '"[^"]*"$' | tr -d '"')
|
|
197
|
-
[ "$COMPLETED_AT_VALUE" != "null" ] && [ -n "$COMPLETED_AT_VALUE" ] || {
|
|
198
|
-
echo "[BLOCK] sprint-state.json phase $N 的 completed_at 未设置 (null)"
|
|
199
|
-
echo "[ACTION] 设置 completed_at 为当前时间 (ISO 8601):"
|
|
200
|
-
echo " date -u +%Y-%m-%dT%H:%M:%SZ"
|
|
201
|
-
exit 1
|
|
202
|
-
}
|
|
154
|
+
# ... (完整校验见原规则,phase 编号范围为 1-6)
|
|
203
155
|
```
|
|
204
156
|
|
|
205
|
-
**由 orchestrator 强制执行**,不依赖 subagent 自觉遵守。
|
|
206
|
-
验证失败 → BLOCK,不可 dispatch 下一 Phase。
|
|
207
|
-
|
|
208
157
|
### RESUME GATE / --resume-from 断点校验(Issue #148)
|
|
209
158
|
|
|
210
159
|
当使用 `--resume-from <phase>` 时,在执行 Phase Transition Gate 之前,
|
|
211
|
-
orchestrator MUST
|
|
212
|
-
|
|
213
|
-
```bash
|
|
214
|
-
SPRINT_STATE=".sprint-state/sprint-state.json"
|
|
215
|
-
[ -f "$SPRINT_STATE" ] || { echo "[BLOCK] sprint-state.json 不存在,无法恢复"; exit 1; }
|
|
216
|
-
|
|
217
|
-
# 1. Sprint ID 一致性:确认 resume 的目标 sprint 与 sprint-state.json 匹配
|
|
218
|
-
SPRINT_ID=$(grep -o '"id": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
219
|
-
CURRENT_SPRINT_ID=$(echo "$TASK_DESCRIPTION" | md5sum | head -8 2>/dev/null || echo "unknown")
|
|
220
|
-
# 实际 sprint id 由 Phase -1 生成,此处仅验证文件存在且包含 id 字段
|
|
221
|
-
[ -n "$SPRINT_ID" ] || { echo "[BLOCK] sprint-state.json 缺少 id 字段"; exit 1; }
|
|
222
|
-
|
|
223
|
-
# 2. 阶段顺序校验:--resume-from 的 phase 必须是最后已完成 phase 的后继
|
|
224
|
-
LAST_COMPLETED_PHASE=$(grep -o '"phase": [0-9]' "$SPRINT_STATE" | tail -1 | awk '{print $2}')
|
|
225
|
-
RESUME_PHASE=$((RESUME_PHASE)) # orchestrator 将 --resume-from 参数值转为整数
|
|
226
|
-
[ "$RESUME_PHASE" -gt "$LAST_COMPLETED_PHASE" ] || {
|
|
227
|
-
echo "[BLOCK] --resume-from phase ($RESUME_PHASE) 必须在最后已完成 phase ($LAST_COMPLETED_PHASE) 之后"
|
|
228
|
-
exit 1
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
# 3. Git 状态校验:isolation branch 仍然可达
|
|
232
|
-
ISOLATION_BRANCH=$(grep -o '"branch": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
233
|
-
ISOLATION_COMMIT=$(grep -o '"created_from_commit": "[^"]*"' "$SPRINT_STATE" | head -1 | cut -d'"' -f4)
|
|
234
|
-
if [ -n "$ISOLATION_BRANCH" ]; then
|
|
235
|
-
git rev-parse --verify "$ISOLATION_BRANCH" >/dev/null 2>&1 || {
|
|
236
|
-
echo "[BLOCK] isolation branch '$ISOLATION_BRANCH' 已不存在(可能被删除或 force push 覆盖)"
|
|
237
|
-
exit 1
|
|
238
|
-
}
|
|
239
|
-
fi
|
|
240
|
-
if [ -n "$ISOLATION_COMMIT" ]; then
|
|
241
|
-
git cat-file -e "${ISOLATION_COMMIT}^{commit}" 2>/dev/null || {
|
|
242
|
-
echo "[WARN] isolation commit $ISOLATION_COMMIT 不可达(可能被 GC 或 rebase 清理),恢复后可能状态不一致"
|
|
243
|
-
# WARN 而非 BLOCK — 可继续但有风险
|
|
244
|
-
}
|
|
245
|
-
fi
|
|
246
|
-
|
|
247
|
-
# 4. 文件时效性校验:前置摘要文件的 mtime 不晚于其生成 phase 的完成时间
|
|
248
|
-
RESUME_PREREQ_PHASE=$((RESUME_PHASE - 1))
|
|
249
|
-
PREREQ_FILE=".sprint-state/phase-outputs/phase-${RESUME_PREREQ_PHASE}-summary.md"
|
|
250
|
-
[ -f "$PREREQ_FILE" ] || { echo "[BLOCK] 前置摘要文件 ${PREREQ_FILE} 不存在"; exit 1; }
|
|
251
|
-
|
|
252
|
-
# 提取前置 phase 的完成时间
|
|
253
|
-
PREREQ_COMPLETED_AT=$(grep -A3 "\"phase\": $RESUME_PREREQ_PHASE" "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | cut -d'"' -f4)
|
|
254
|
-
if [ -n "$PREREQ_COMPLETED_AT" ] && [ "$PREREQ_COMPLETED_AT" != "null" ]; then
|
|
255
|
-
FILE_MTIME=$(stat -c %Y "$PREREQ_FILE" 2>/dev/null || stat -f %m "$PREREQ_FILE" 2>/dev/null)
|
|
256
|
-
COMPLETED_EPOCH=$(date -d "$PREREQ_COMPLETED_AT" +%s 2>/dev/null || echo "")
|
|
257
|
-
if [ -n "$FILE_MTIME" ] && [ -n "$COMPLETED_EPOCH" ]; then
|
|
258
|
-
# 容忍 60 秒时钟偏差
|
|
259
|
-
[ "$FILE_MTIME" -le $((COMPLETED_EPOCH + 60)) ] || {
|
|
260
|
-
echo "[WARN] 前置摘要文件 ${PREREQ_FILE} 在 phase $RESUME_PREREQ_PHASE 完成后被修改(mtime: $(date -d @$FILE_MTIME '+%Y-%m-%d %H:%M:%S'), completed_at: $PREREQ_COMPLETED_AT)"
|
|
261
|
-
echo "[ACTION] 继续恢复前请确认修改是预期的。输入 'confirm' 继续,其他取消:"
|
|
262
|
-
read USER_CONFIRM
|
|
263
|
-
[ "$USER_CONFIRM" = "confirm" ] || { echo "[BLOCK] 用户取消恢复"; exit 1; }
|
|
264
|
-
}
|
|
265
|
-
fi
|
|
266
|
-
fi
|
|
267
|
-
|
|
268
|
-
# 5. specification.yaml 时效性校验(仅 --resume-from build)
|
|
269
|
-
SPEC_FILE="specification.yaml"
|
|
270
|
-
if [ "$RESUME_PHASE" -ge 2 ] && [ -f "$SPEC_FILE" ]; then
|
|
271
|
-
SPEC_MTIME=$(stat -c %Y "$SPEC_FILE" 2>/dev/null || stat -f %m "$SPEC_FILE" 2>/dev/null)
|
|
272
|
-
PLAN_COMPLETED_AT=$(grep -A3 '"phase": 1' "$SPRINT_STATE" 2>/dev/null | grep "completed_at" | head -1 | cut -d'"' -f4)
|
|
273
|
-
if [ -n "$SPEC_MTIME" ] && [ -n "$PLAN_COMPLETED_AT" ] && [ "$PLAN_COMPLETED_AT" != "null" ]; then
|
|
274
|
-
PLAN_EPOCH=$(date -d "$PLAN_COMPLETED_AT" +%s 2>/dev/null || echo "")
|
|
275
|
-
if [ -n "$PLAN_EPOCH" ] && [ "$SPEC_MTIME" -gt $((PLAN_EPOCH + 60)) ]; then
|
|
276
|
-
echo "[WARN] specification.yaml 在 Plan phase 完成后被修改"
|
|
277
|
-
echo "[ACTION] 继续恢复前请确认 specification.yaml 的修改是预期的。输入 'confirm' 继续:"
|
|
278
|
-
read USER_CONFIRM
|
|
279
|
-
[ "$USER_CONFIRM" = "confirm" ] || { echo "[BLOCK] 用户取消恢复"; exit 1; }
|
|
280
|
-
fi
|
|
281
|
-
fi
|
|
282
|
-
fi
|
|
283
|
-
|
|
284
|
-
echo "✅ RESUME GATE PASSED — 断点校验通过"
|
|
285
|
-
# 继续执行 Phase Transition Gate
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
验证失败 → BLOCK,不可执行 `--resume-from`。
|
|
289
|
-
orchestrator 必须展示失败原因并建议用户启动新 Sprint 或手动修复后重试。
|
|
160
|
+
orchestrator MUST 先执行断点校验。与新 6-phase 模型一致,phase 编号使用 1-6。
|
|
290
161
|
|
|
291
162
|
### WORKTREE ENFORCEMENT(Issue #84)
|
|
292
163
|
|
|
293
|
-
Phase
|
|
294
|
-
|
|
295
|
-
- **工作目录**:所有 Bash 命令必须通过 `workdir` 参数或 `&&` 链式命令在 worktree 路径下执行
|
|
164
|
+
Phase 1/6 PREP 执行完毕后,**所有后续操作(Phase 2/6 到 Phase 6/6)的文件编辑、命令执行 MUST 在 worktree 目录下执行**:
|
|
165
|
+
- **工作目录**:所有 Bash 命令必须通过 `workdir` 参数在 worktree 路径下执行
|
|
296
166
|
- **文件写入**:所有 `write`、`edit` 工具的 `filePath` 必须位于 `isolation.worktree_path` 下
|
|
297
|
-
-
|
|
298
|
-
|
|
167
|
+
- **例外**:`.gitignore` 校验和 `git worktree remove`(Phase 6/6 CLOSE 清理)在仓库根目录执行
|
|
168
|
+
|
|
299
169
|
Sprint state is persisted as JSON in `.sprint-state/sprint-state.json`:
|
|
300
170
|
```json
|
|
301
171
|
{
|
|
302
|
-
"id": "sprint-2026-
|
|
172
|
+
"id": "sprint-2026-07-08-01",
|
|
303
173
|
"task_description": "开发访谈机器人,支持多轮对话",
|
|
304
|
-
"phase":
|
|
174
|
+
"phase": 1,
|
|
305
175
|
"status": "running|paused|completed",
|
|
306
|
-
"started_at": "2026-
|
|
176
|
+
"started_at": "2026-07-08T10:00:00Z",
|
|
307
177
|
"isolation": {
|
|
308
|
-
"worktree_path": ".worktrees/sprint/sprint-2026-
|
|
309
|
-
"branch": "sprint/2026-
|
|
178
|
+
"worktree_path": ".worktrees/sprint/sprint-2026-07-08-01",
|
|
179
|
+
"branch": "sprint/2026-07-08-01",
|
|
310
180
|
"created_from": "main",
|
|
311
181
|
"created_from_commit": "abc123def..."
|
|
312
182
|
},
|
|
@@ -321,19 +191,19 @@ Sprint state is persisted as JSON in `.sprint-state/sprint-state.json`:
|
|
|
321
191
|
"test_file_count": 4
|
|
322
192
|
},
|
|
323
193
|
"estimated_level": "轻量|标准|复杂",
|
|
324
|
-
"recommended_flow": "
|
|
194
|
+
"recommended_flow": "轻量流程|标准流程|完整 Sprint Flow (6 phases)",
|
|
325
195
|
"risk_warnings": ["循环依赖: user ↔ plane"],
|
|
326
196
|
"user_decision": "accepted|overridden|cancelled",
|
|
327
197
|
"override_reason": null
|
|
328
198
|
},
|
|
329
199
|
"phase_history": [
|
|
330
200
|
{
|
|
331
|
-
"phase":
|
|
332
|
-
"phase_name": "
|
|
201
|
+
"phase": 1,
|
|
202
|
+
"phase_name": "PREP",
|
|
333
203
|
"status": "completed",
|
|
334
|
-
"started_at": "2026-
|
|
335
|
-
"completed_at": "2026-
|
|
336
|
-
"duration_seconds":
|
|
204
|
+
"started_at": "2026-07-08T10:00:00Z",
|
|
205
|
+
"completed_at": "2026-07-08T10:05:00Z",
|
|
206
|
+
"duration_seconds": 300
|
|
337
207
|
}
|
|
338
208
|
],
|
|
339
209
|
"outputs": {
|
|
@@ -351,15 +221,9 @@ Sprint state is persisted as JSON in `.sprint-state/sprint-state.json`:
|
|
|
351
221
|
```
|
|
352
222
|
|
|
353
223
|
**新增字段说明**:
|
|
354
|
-
- `task_description`: Sprint 需求描述(Phase
|
|
355
|
-
- `started_at`: Sprint 启动时间戳(Phase
|
|
356
|
-
- `phase_history`:
|
|
357
|
-
|
|
358
|
-
- `phase_name`: 阶段名称
|
|
359
|
-
- `status`: completed / running / failed / skipped
|
|
360
|
-
- `started_at`: 阶段开始时间(ISO 8601)
|
|
361
|
-
- `completed_at`: 阶段完成时间(null 表示未完成)
|
|
362
|
-
- `duration_seconds`: 耗时秒数(null 表示未完成)
|
|
224
|
+
- `task_description`: Sprint 需求描述(Phase 1/6 PREP 启动时写入)
|
|
225
|
+
- `started_at`: Sprint 启动时间戳(Phase 1/6 PREP 启动时写入,ISO 8601 格式)
|
|
226
|
+
- `phase_history`: 阶段历史数组,每个元素记录阶段的执行信息(phase 编号 1-6)
|
|
227
|
+
- **Backward compat**: Legacy phase numbers (-1, -0.5, 0..8) in old sprint-state.json files remain readable
|
|
363
228
|
|
|
364
229
|
**Eval assertions check for:** `phase`, `status`, `isolation.branch`, `outputs.specification`, `metrics.coverage_pct`, `phase_history`, `task_description`.
|
|
365
|
-
|