@boyingliu01/xp-gate 0.10.11 → 0.10.13

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 (50) hide show
  1. package/lib/__tests__/check-version.test.js +19 -5
  2. package/lib/__tests__/doctor.test.js +155 -0
  3. package/lib/__tests__/install-skill.test.js +1 -1
  4. package/lib/doctor.js +126 -0
  5. package/lib/init.js +12 -0
  6. package/mock-policy/AGENTS.md +3 -3
  7. package/mutation/AGENTS.md +3 -3
  8. package/package.json +1 -1
  9. package/plugins/claude-code/.claude-plugin/plugin.json +1 -1
  10. package/plugins/claude-code/skills/delphi-review/AGENTS.md +3 -3
  11. package/plugins/claude-code/skills/sprint-flow/AGENTS.md +3 -3
  12. package/plugins/claude-code/skills/sprint-flow/SKILL.md +6 -9
  13. package/plugins/claude-code/skills/sprint-flow/references/orchestration-rules.md +8 -6
  14. package/plugins/claude-code/skills/sprint-flow/references/phase-1-plan.md +2 -2
  15. package/plugins/claude-code/skills/sprint-flow/references/phase-3-review.md +3 -1
  16. package/plugins/claude-code/skills/test-specification-alignment/AGENTS.md +3 -3
  17. package/plugins/opencode/__tests__/tui-plugin.test.ts +121 -1
  18. package/plugins/opencode/__tests__/xp-gate-e2e-upgrade.test.ts +562 -0
  19. package/plugins/opencode/index.ts +2 -0
  20. package/plugins/opencode/package.json +1 -1
  21. package/plugins/opencode/skills/delphi-review/AGENTS.md +3 -3
  22. package/plugins/opencode/skills/sprint-flow/AGENTS.md +3 -3
  23. package/plugins/opencode/skills/sprint-flow/SKILL.md +6 -9
  24. package/plugins/opencode/skills/sprint-flow/references/orchestration-rules.md +8 -6
  25. package/plugins/opencode/skills/sprint-flow/references/phase-1-plan.md +2 -2
  26. package/plugins/opencode/skills/sprint-flow/references/phase-3-review.md +3 -1
  27. package/plugins/opencode/skills/test-specification-alignment/AGENTS.md +3 -3
  28. package/plugins/opencode/tui-plugin.ts +24 -7
  29. package/plugins/qoder/plugin.json +1 -1
  30. package/plugins/qoder/skills/delphi-review/AGENTS.md +3 -3
  31. package/plugins/qoder/skills/sprint-flow/AGENTS.md +3 -3
  32. package/plugins/qoder/skills/sprint-flow/SKILL.md +191 -1088
  33. package/plugins/qoder/skills/sprint-flow/references/orchestration-rules.md +365 -0
  34. package/plugins/qoder/skills/sprint-flow/references/phase-1-plan.md +2 -2
  35. package/plugins/qoder/skills/sprint-flow/references/phase-2-build.md +25 -180
  36. package/plugins/qoder/skills/sprint-flow/references/phase-3-review.md +3 -1
  37. package/plugins/qoder/skills/sprint-flow/references/phase-6-ship.md +4 -188
  38. package/plugins/qoder/skills/sprint-flow/references/phase-7-land.md +4 -135
  39. package/plugins/qoder/skills/sprint-flow/references/phase-8-cleanup.md +4 -187
  40. package/plugins/qoder/skills/sprint-flow/references/phase-minus-0-5-auto-estimate.md +6 -0
  41. package/plugins/qoder/skills/sprint-flow/references/phase-minus-1-isolate.md +58 -0
  42. package/plugins/qoder/skills/test-specification-alignment/AGENTS.md +3 -3
  43. package/principles/AGENTS.md +3 -3
  44. package/skills/delphi-review/AGENTS.md +3 -3
  45. package/skills/sprint-flow/AGENTS.md +3 -3
  46. package/skills/sprint-flow/SKILL.md +6 -9
  47. package/skills/sprint-flow/references/orchestration-rules.md +8 -6
  48. package/skills/sprint-flow/references/phase-1-plan.md +2 -2
  49. package/skills/sprint-flow/references/phase-3-review.md +3 -1
  50. package/skills/test-specification-alignment/AGENTS.md +3 -3
@@ -0,0 +1,365 @@
1
+ ## 编排层规则(Orchestration Rules)
2
+
3
+ ### Agent Dispatch Rules
4
+
5
+ | Agent Type | 适用场景 | 不适用场景 | 超时处理 |
6
+ |-----------|---------|-----------|---------|
7
+ | `explore` (bare) | **窄搜索**:单个关键词/pattern,已知文件位置 | 多角度宽泛搜索,读取大文件,3+ search angles | >5min → cancel + 用 `deep` 重试 |
8
+ | `librarian` (bare) | **外部参考**:API 文档、OSS 示例 | 内部代码库宽泛探索 | >5min → cancel + 用 `deep` 重试 |
9
+ | `task(category="deep")` | **复杂研究**:多模块分析,架构决策 | 单文件 trivial fix | 无限制 |
10
+ | `task(category="unspecified-high")` | **高 effort 实现**:新模块、重构 | 单行修改 | 无限制 |
11
+
12
+ **关键规则**:
13
+
14
+ 1. Bare `explore` agent 本质是 contextual grep,**不是研究 agent**。如果任务涉及:
15
+ - 3+ 个独立搜索角度
16
+ - 读取多个大文件(>200 行)
17
+ - 需要跨层分析(如"查 ralph-loop + .sprint-state/ + token 阈值 + phase transition")
18
+
19
+ → **必须用 `task(category="deep", load_skills=[...])` 替代**
20
+
21
+ 2. 如果 `explore` agent >5 分钟未返回 → cancel 并立即用 `task(category="deep")` 重试。不要等待。
22
+
23
+ 3. **并行 explore 仍然是正确模式**。2-4 个窄搜索 explore agent 并行执行是高效且推荐的。问题在于给单一 explore agent 分配宽泛任务。
24
+
25
+ **issue #83 根因**:`bg_1abf2ed9` 被分配了 4 个独立搜索角度的宽泛任务(ralph-loop context + .sprint-state/ + token threshold + phase transition),bare explore agent 超时丢失 session。同批的 `bg_5ecf590d`(窄搜索 OpenCode compaction API)3m35s 正常完成。
26
+
27
+ ### Phase Subagent Dispatch Matrix
28
+
29
+ | Phase | 名称 | Subagent? | Category | load_skills | 执行者 |
30
+ |-------|------|:---------:|----------|-------------|--------|
31
+ | -1 | ISOLATE | ❌ | Bash(直接执行) | 无 | orchestrator |
32
+ | -0.5 | AUTO-ESTIMATE | ❌ | Bash(直接执行) | 无 | orchestrator |
33
+ | 0 | THINK | ❌ | orchestrator(直接执行) | `["brainstorming"]` | orchestrator |
34
+ | 1 | PLAN | ❌ | orchestrator(直接执行) | `["autoplan", "delphi-review", "to-issues"]` | orchestrator |
35
+ | 2 | BUILD | ✅ | ralph-loop | `["test-driven-development"]` | subagent |
36
+ | 3 | REVIEW | ❌ | orchestrator(直接执行) | `["delphi-review", "test-specification-alignment"]` | orchestrator |
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 |
42
+
43
+ **⚠️ 交互式 skill 必须由 orchestrator 直接执行(不可 dispatch 到 subagent)**:
44
+
45
+ | Phase | Skill | 为什么不能在 subagent 中执行 |
46
+ |-------|-------|---------------------------|
47
+ | 0 | `brainstorming` | 需要与用户对话确认需求、提出澄清问题。Subagent 是 fire-and-forget 模式,无法暂停等待用户输入(Issue #217) |
48
+ | 1 | `autoplan` | taste_decisions 节点暂停等待用户确认。必须由 orchestrator 直接执行(Issue #225) |
49
+ | 1 | `delphi-review` | design 模式需等待 verdict APPROVED;非 APPROVED 时需用户确认是否接受分歧方案(Issue #249) |
50
+ | 1 | `to-issues` | Step 6 "向用户确认" — 展示拆分结果,等待用户批准后才生成 slices-manifest.json |
51
+ | 3 | `delphi-review --mode code-walkthrough` | Code walkthrough 非 APPROVED 时需暂停等待用户处理 Critical Issues(Issue #249) |
52
+ | 6 | `finishing-a-development-branch` | 4 选项菜单 (merge/PR/keep/discard) 需要用户选择;Option 4 (discard) 要求 typed confirmation |
53
+ | 6 | `ship` | PR 创建前需要用户确认;包含 AskUserQuestion STOP 点 |
54
+ | 7 | `land-and-deploy` | Merge 确认、rollback 决策 — 均为用户交互点 |
55
+
56
+ **Phase 1 执行模式(全部 orchestrator 直接执行)**:
57
+ 1. **Orchestrator 直接执行 autoplan**:`skill(name="autoplan")` → 等待用户确认 taste_decisions
58
+ 2. **Orchestrator 直接执行 delphi-review**:`skill(name="delphi-review")` → 等待 APPROVED(非 APPROVED 时暂停等待用户确认)
59
+ 3. **Orchestrator 直接执行 to-issues**:`skill(name="to-issues")` → 等待用户确认 Issue 拆分
60
+
61
+ **上下文隔离原则**:
62
+ - 每个 Subagent 在**独立 session** 中启动,不继承 orchestrator 的对话历史
63
+ - orchestrator session 仅接收 subagent 的最终结果摘要(~13,000 tokens/sprint)
64
+ - 现代模型百万 token 上下文 + 缓存命中 → 单 sprint 不会触发 overflow
65
+
66
+ ### CONTEXT INHERITANCE
67
+
68
+ 每个 Phase subagent 启动时,上下文仅通过以下路径继承:
69
+
70
+ | Phase | 加载来源 | 内容 |
71
+ |-------|---------|------|
72
+ | Phase -1 | 无前置(Bash 操作) | 用户原始需求 + 当前分支状态 |
73
+ | Phase 0 | phase--1-summary(仅路径) | 隔离环境信息(worktree 路径) |
74
+ | Phase 1 | phase-0-summary.md + design-doc | 设计决策 + 结构化规格 |
75
+ | Phase 2 | phase-1-summary.md + specification.yaml | 评审结论 + REQ 列表 |
76
+ | Phase 3 | phase-2-summary.md + MVP 代码 | 构建结果(orchestrator 直接执行,无 subagent 上下文继承) |
77
+ | Phase 4 | — | **人工验收**。Phase 4 不产生 subagent summary,但用户验收结果记录在 `.sprint-state/phase-outputs/emergent-issues.md`(如有 emergent issues)。Phase 5 加载此文件。 |
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 操作) | 部署结果 |
82
+
83
+ **隔离原则**:每个 Phase subagent 在干净上下文中启动。
84
+ 输入仅限上表对应的摘要文件和一级产出物。
85
+ 不包含前一 Phase 的完整对话、中间文件、失败尝试。
86
+
87
+ **特殊场景**:
88
+ - `--resume-from <phase>`:跳过前置 Phase,直接从指定 Phase 启动。**MUST 先执行 RESUME GATE(Issue #148)** 校验 sprint 状态、git 可达性和文件时效性,再执行 Phase Transition Gate 校验摘要文件格式。例如 `--resume-from build` 要求 `phase-1-summary.md` 和 `specification.yaml` 已存在且非 stale。
89
+ - `--no-isolate`:跳过 Phase -1 ISOLATE,直接在当前分支执行。Phase 0 无 `phase--1-summary` 可用,上下文继承来源为用户原始需求 + 当前 git 状态。所有后续 Phase 的 worktree enforcement 不适用(无 worktree),但仍需保持代码隔离。
90
+ - `next_phase_context` 中的 `{path}` 等变量占位符在实际写入时被替换为具体值。示例中的 `{path}` 应替换为实际 worktree 路径(如 `.worktrees/sprint/sprint-2026-06-01-01`)。
91
+
92
+ ### PHASE TRANSITION RULES
93
+
94
+ 每个 Phase subagent 完成后,必须按顺序执行以下步骤:
95
+
96
+ 1. **写入 Phase 摘要**:创建 `.sprint-state/phase-outputs/phase-{N}-summary.md`
97
+ - 格式:YAML frontmatter + Markdown body(body ≤ 50 行)
98
+ - 大小限制:≤ 40,000 字符(≈ 10,000 tokens)
99
+
100
+ 2. **更新 sprint-state.json**:
101
+ - `phase`: 当前阶段编号
102
+ - `outputs`: 新增当前阶段输出文件路径
103
+ - `phase_history`: 追加或更新当前阶段的记录
104
+ - 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`(`completed_at - started_at` 的秒数)
106
+ - Phase 跳过时(如轻量路由跳过 Phase 0 brainstorming):设置 `status: "skipped"`
107
+
108
+ 3. **等待用户确认 checkpoint**(如适用)
109
+
110
+ 4. **展示进度看板**:执行 `node scripts/render-sprint-progress.cjs` 渲染进度看板
111
+ - 脚本自动读取 `.sprint-state/sprint-state.json` 并输出 ASCII 进度看板
112
+ - 渲染规则:已完成阶段显示 ✅ + 耗时,当前阶段 🔄,待做 ⬜,跳过 ⏭️,失败 ❌
113
+ - 进度条:`[████▓░░░░░░] {pct}%`(已完成数/总阶段数 11)
114
+ - 下一步行动:根据当前阶段 + 状态,自动查找对应提示
115
+ - 输出物路径:列出 `outputs` 中已有的文件路径
116
+ - 时机:每个 Phase 完成后的 transition 阶段自动展示,用户无需请求
117
+ - 向后兼容:旧版 `sprint-state.json` 缺少 `phase_history` 时,从 `phase` 字段推断状态
118
+
119
+ ### Background Task Resume Protocol (MANDATORY — Issue #248)
120
+
121
+ After dispatching background agents with `run_in_background=true` (e.g., Phase -0.5 AUTO-ESTIMATE explore agents, Phase 1 delphi-review subagent):
122
+
123
+ 1. **END YOUR RESPONSE** — do NOT poll `background_output()` before receiving `<system-reminder>`
124
+ 2. **On `<system-reminder>` notification**: collect ALL completed results via `background_output(task_id="bg_...")`
125
+ 3. **When ALL tasks complete**: immediately resume by:
126
+ a. Synthesizing results into the current phase assessment
127
+ b. Executing the phase transition gate
128
+ c. Continuing to the next phase **WITHOUT waiting for human input**
129
+ 4. **If any task failed**: collect partial results, log the failure, continue with available data (do NOT block the pipeline)
130
+
131
+ **The orchestrator MUST treat task completion notifications as an implicit "continue" signal.** This protocol prevents the "human-in-loop stall" where all background tasks complete but the orchestrator waits indefinitely for a human message (Issue #235, #248).
132
+
133
+ ### Phase Summary 格式(YAML Frontmatter Schema)
134
+
135
+ 每个 `phase-N-summary.md` 必须包含以下 YAML frontmatter:
136
+
137
+ ```markdown
138
+ ---
139
+ phase: -1
140
+ phase_name: ISOLATE
141
+ status: completed
142
+ outputs:
143
+ - path: ".worktrees/sprint/sprint-YYYY-MM-DD-NN"
144
+ type: directory
145
+ decisions:
146
+ - title: "Worktree isolation enabled"
147
+ rationale: "Prevent main branch pollution"
148
+ unresolved_issues: []
149
+ next_phase_context: "Worktree created at {path}. All subsequent edits MUST use this workdir."
150
+ ---
151
+
152
+ ## Phase Summary
153
+ {简明摘要,不超过 50 行}
154
+ ```
155
+
156
+ **必填字段**: `phase`, `phase_name`, `status`, `outputs`, `decisions`, `next_phase_context`
157
+ **可选字段**: `unresolved_issues`
158
+
159
+ ### Phase Transition Gate
160
+
161
+ Orchestrator dispatch 下一 Phase 前必须执行验证:
162
+
163
+ ```bash
164
+ # === Phase Transition Gate ===
165
+
166
+ # 1. Phase summary file validation
167
+ SUMMARY=".sprint-state/phase-outputs/phase-${N}-summary.md"
168
+ [ -f "$SUMMARY" ] || { echo "[BLOCK] phase-${N}-summary 不存在"; exit 1; }
169
+ FRONTMARKERS=$(grep -c "^---" "$SUMMARY" 2>/dev/null || echo 0)
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
+ }
203
+ ```
204
+
205
+ **由 orchestrator 强制执行**,不依赖 subagent 自觉遵守。
206
+ 验证失败 → BLOCK,不可 dispatch 下一 Phase。
207
+
208
+ ### RESUME GATE / --resume-from 断点校验(Issue #148)
209
+
210
+ 当使用 `--resume-from <phase>` 时,在执行 Phase Transition Gate 之前,
211
+ orchestrator MUST 先执行以下断点校验。任何一项失败 → BLOCK,拒绝恢复。
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 或手动修复后重试。
290
+
291
+ ### WORKTREE ENFORCEMENT(Issue #84)
292
+
293
+ Phase -1 执行完毕后,**所有后续操作(Phase 0 到 Phase 8)的文件编辑、命令执行 MUST 在 worktree 目录下执行**:
294
+
295
+ - **工作目录**:所有 Bash 命令必须通过 `workdir` 参数或 `&&` 链式命令在 worktree 路径下执行
296
+ - **文件写入**:所有 `write`、`edit` 工具的 `filePath` 必须位于 `isolation.worktree_path` 下
297
+ - **验证步骤**:Phase 0 开始前,输出 `[WORKTREE] 后续所有操作将在 {worktree_path} 中进行`
298
+ - **例外**:`.gitignore` 校验(Phase -1 表步 4)和 `git worktree remove`(Phase 8 清理)在仓库根目录执行
299
+ Sprint state is persisted as JSON in `.sprint-state/sprint-state.json`:
300
+ ```json
301
+ {
302
+ "id": "sprint-2026-04-26-01",
303
+ "task_description": "开发访谈机器人,支持多轮对话",
304
+ "phase": -1,
305
+ "status": "running|paused|completed",
306
+ "started_at": "2026-04-26T10:00:00Z",
307
+ "isolation": {
308
+ "worktree_path": ".worktrees/sprint/sprint-2026-04-26-01",
309
+ "branch": "sprint/2026-04-26-01",
310
+ "created_from": "main",
311
+ "created_from_commit": "abc123def..."
312
+ },
313
+ "auto_estimate": {
314
+ "change_type": "删除已存在代码|修改已存在代码|新增功能|Bug修复",
315
+ "metrics": {
316
+ "ref_count": 12,
317
+ "cross_module_count": 3,
318
+ "modules": ["auth", "user", "admin"],
319
+ "circular_dep": true,
320
+ "public_api_count": 5,
321
+ "test_file_count": 4
322
+ },
323
+ "estimated_level": "轻量|标准|复杂",
324
+ "recommended_flow": "轻量流程 (Phase 0-3, reduced-intensity Delphi)|标准流程 (Phase 0-4)|完整 Sprint Flow (Phase 0-8)",
325
+ "risk_warnings": ["循环依赖: user ↔ plane"],
326
+ "user_decision": "accepted|overridden|cancelled",
327
+ "override_reason": null
328
+ },
329
+ "phase_history": [
330
+ {
331
+ "phase": -1,
332
+ "phase_name": "ISOLATE",
333
+ "status": "completed",
334
+ "started_at": "2026-04-26T10:00:00Z",
335
+ "completed_at": "2026-04-26T10:03:00Z",
336
+ "duration_seconds": 180
337
+ }
338
+ ],
339
+ "outputs": {
340
+ "pain_document": "docs/pain-document.md",
341
+ "specification": "specification.yaml",
342
+ "mvp": "mvp-v1/",
343
+ "review_report": "review-report.md"
344
+ },
345
+ "metrics": {
346
+ "tests_passed": 15,
347
+ "tests_failed": 0,
348
+ "coverage_pct": 85
349
+ }
350
+ }
351
+ ```
352
+
353
+ **新增字段说明**:
354
+ - `task_description`: Sprint 需求描述(Phase -1 启动时写入)
355
+ - `started_at`: Sprint 启动时间戳(Phase -1 启动时写入,ISO 8601 格式)
356
+ - `phase_history`: 阶段历史数组,每个元素记录阶段的执行信息:
357
+ - `phase`: 阶段编号
358
+ - `phase_name`: 阶段名称
359
+ - `status`: completed / running / failed / skipped
360
+ - `started_at`: 阶段开始时间(ISO 8601)
361
+ - `completed_at`: 阶段完成时间(null 表示未完成)
362
+ - `duration_seconds`: 耗时秒数(null 表示未完成)
363
+
364
+ **Eval assertions check for:** `phase`, `status`, `isolation.branch`, `outputs.specification`, `metrics.coverage_pct`, `phase_history`, `task_description`.
365
+
@@ -105,7 +105,7 @@ Decision 2: [决策描述]
105
105
 
106
106
  ---
107
107
 
108
- ### Step 2b: 调用 delphi-review(强制)
108
+ ### Step 2b: 调用 delphi-review(强制,orchestrator 直接执行)
109
109
 
110
110
  ```bash
111
111
  skill(name="delphi-review", user_message="[设计文档 + taste_decisions 确认结果]")
@@ -117,7 +117,7 @@ delphi-review 执行:
117
117
  - 输出: APPROVED / REQUEST_CHANGES
118
118
 
119
119
  **如果 REQUEST_CHANGES**:
120
- - ⚠️ 暂停等待用户修复
120
+ - ⚠️ 暂停等待用户处理(orchestrator 直接执行,可交互确认)
121
121
  - 修复后重新评审(从 Round 2 起步)
122
122
  - 直到 APPROVED
123
123
 
@@ -1,198 +1,43 @@
1
1
  # Phase 2: BUILD(TDD + 并行执行 + 盲评 + 验证)
2
2
 
3
- ## 目标
3
+ **完整指令**: @see SKILL.md `## Phase 2: BUILD` section.
4
4
 
5
- TDD 执行,多 Agent 并行加速,盲评验证,Gate 1 验证通过。生成 MVP v1。
5
+ **摘要**: TDD 执行, Agent 并行加速, 盲评验证, Gate 1 验证通过。
6
6
 
7
- ---
8
-
9
- ## 调用 Skills
7
+ **关键链路**: DELPHI-GATE → parallel-dispatch/ralph-loop → TDD → freeze → blind-review → unfreeze → verification → cost monitor
10
8
 
11
- | 步骤 | Skill | 来源 | 说明 |
12
- |------|-------|------|------|
13
- | 0 | **`dispatching-parallel-agents`** _(新增)_ | superpowers | 检测可并行任务,并行分发独立子任务 |
14
- | 0 | **`executing-plans`** _(新增)_ | superpowers | 在隔离 session 中执行计划,有 review checkpoint |
15
- | 1 | `test-driven-development` | superpowers | RED → GREEN → REFACTOR 铁律 |
16
- | 1.5 | `vercel-react-native-skills` | gstack | React Native 特定测试框架引用(如适用) |
17
- | 2 | `freeze` | gstack | 锁定业务代码,盲评隔离 |
18
- | 3 | `requesting-code-review` | superpowers | 独立 agent 盲评(隔离状态) |
19
- | 4 | `unfreeze` | gstack | 解锁业务代码 |
20
- | 5 | `verification-before-completion` | superpowers | 测试 + lint 证据优先 |
21
- | 6 | 成本监控 | sprint-flow 编排层 | 超阈值 BLOCK + 用户决策 |
9
+ **输出**: MVP v1
22
10
 
23
11
  ---
24
12
 
25
- ## 执行步骤
26
-
27
- ### Step 0: 并行检测与任务分发(新增 — ISSUE29)
28
-
29
- **检测可并行任务**:
30
- 从 specification.yaml 或 Phase 1 输出中提取独立任务。并行条件:
31
- - 无共享状态依赖(不读写同一文件)
32
- - 无文件冲突风险(不同模块/组件)
33
- - 2+ 独立任务存在
34
-
35
- **IF 检测到可并行任务 → dispatching-parallel-agents 模式**:
36
-
37
- ```
38
- Phase 2:
39
- ├── task: [独立A] ──┐
40
- ├── task: [独立B] ──┼── dispatching-parallel-agents (并行)
41
- ├── task: [独立C] ──┘
42
- └── merge → freeze → review → verification
43
- ```
44
-
45
- 每个独立任务调用:
46
- ```
47
- skill(name="executing-plans", user_message="[计划内容] + review checkpoint")
48
- ```
49
-
50
- **IF 无并行机会 → 串行模式**(保持现有行为):
51
- ```
52
- Phase 2: test-driven-development → freeze → review → verification
53
- ```
13
+ ## Gate 参考表(Phase 2 相关)
54
14
 
55
- ### Step 1: TDD 执行(test-driven-development)
56
-
57
- ```
58
- skill(name="test-driven-development", user_message="[需求描述],基于 specification.yaml")
59
- ```
60
-
61
- **TDD 铁律**:
62
- 1. 🔴 **RED**: 先写测试(根据 specification.yaml 的 acceptance_criteria)
63
- 2. 🟢 **GREEN**: 写最小实现代码让测试通过
64
- 3. 🔵 **REFACTOR**: 重构代码,保持测试通过
65
-
66
- **语言特定 TDD**(通过 `--lang` 参数选择):
67
-
68
- | 语言 | 调用的 TDD skill |
69
- |------|-----------------|
70
- | Spring Boot | `springboot-tdd` |
71
- | Django | `django-tdd` |
72
- | Go | `golang-testing` |
73
-
74
- **输出**: tests + code
75
-
76
- ### Step 1.5: React Native 特定 TDD(如适用)
77
-
78
- **移动端项目特定测试策略**:
79
-
80
- 对于 mobile-react-native 项目:
81
- - 检测 `--type mobile-react-native` 或 `package.json` 中包含 react-native 依赖
82
- - 使用 Jest 进行单元测试 (RN 默认)
83
- - 使用 Detox 进行端到端测试
84
- - 使用 React Native Testing Library 进行组件测试
85
- - TDD 流程: 先写组件测试 → 极简组件实现 → 通过测试 → 重构
86
-
87
- 配置文件:
88
- - `jest.config.js` 用于测试环境设置
89
- - `.detoxrc.js` 包含 Detox 配置
90
- - iOS/Android 模拟器/真机测试支持
91
-
92
- **执行顺序**:
93
- - `npx jest` 运行单元测试
94
- - `npx detox build && npx detox test` 运行 E2E 测试
95
- - `npx jest --coverage` 检查测试覆盖率
96
-
97
- **Flutter 项目**(作为补充):
98
- - 对于 mobile-flutter 项目: `flutter test --coverage` 运行单元和 widget 测试
99
-
100
- ### Step 2: 盲评隔离(freeze)
101
-
102
- ```
103
- skill(name="freeze", user_message="[业务代码文件路径]")
104
- ```
105
-
106
- 锁定所有业务代码文件,排除测试文件。
107
- Navigator agent 在盲评阶段将无法访问业务代码。
108
-
109
- ### Step 3: 独立盲评(requesting-code-review)
110
-
111
- ```
112
- skill(name="requesting-code-review", user_message="[需求] + 测试文件 + 测试结果")
113
- ```
114
-
115
- **关键**: 盲评 agent 只接收需求 + 测试 + 测试结果,**不传业务代码**(freeze 锁定中)。
116
-
117
- **输出**: review findings(问题清单 + 建议)
118
-
119
- ### Step 4: 解锁业务代码(unfreeze)
120
-
121
- ```
122
- skill(name="unfreeze", user_message="[业务代码文件路径]")
123
- ```
124
-
125
- 解锁业务代码文件,允许后续步骤访问。
126
-
127
- ### Step 5: 验证(verification-before-completion)
128
-
129
- ```
130
- skill(name="verification-before-completion", user_message="验证实现完整性")
131
- ```
132
-
133
- **验证内容**:
134
- - 测试全部通过
135
- - Lint 无错误
136
- - 覆盖率 ≥ 80%
137
- - 证据优先:必须运行命令并确认输出
138
-
139
- **失败处理**:
140
- - 自动修复 max 3 次
141
- - 每次失败后修复代码,重新运行验证
142
- - max 3 次失败 → ⚠️ BLOCK,暂停等待用户决定
143
-
144
- ### Step 6: 成本监控(sprint-flow 编排层)
145
-
146
- sprint-flow 编排层监控本次 Phase 2 的成本:
147
-
148
- | 阈值 | 值 | 处理 |
149
- |------|-----|------|
150
- | 单任务阈值 | $0.15 | BLOCK + 提示用户决定 |
151
- | 日阈值 | $1.00 | BLOCK + 提示用户决定 |
152
-
153
- **零降级原则**: 成本超阈值时,必须 BLOCK 并通知用户,由用户决定是否继续。AI 不能自动跳过验证步骤。
15
+ | Gate | 名称 | 行为 |
16
+ |------|------|------|
17
+ | Gate 5 | 单元测试 + 覆盖率 | 全部通过 + ≥80% 覆盖率 |
18
+ | Gate 5a-BLOCK | 新增 .ts/.tsx 文件测试强制 | 新增 .ts/.tsx 文件无对应测试文件 → BLOCK;修改文件 → WARNING |
19
+ | Gate M2 | Mock 密度检查 | 30% WARNING (Phase 1); 可配置 via `.mockpolicyrc` |
154
20
 
155
21
  ---
156
22
 
157
- ## 关键行为保留(原 xp-consensus 17 状态机)
23
+ ## TDD 强制执行
158
24
 
159
- | 原状态 | 含义 | 新处理方案 |
160
- |--------|------|-----------|
161
- | `CIRCUIT_BREAKER_TRIGGERED` | 成本/资源超阈值 | sprint-flow 编排层监控成本,超阈值 BLOCK + 用户决策 |
162
- | `ROLLBACK_TO_ROUND1` | Gate 1 失败自动修复 → 回退 | verification-before-completion 失败 → 修复 max 3 次 → 仍失败 BLOCK |
163
- | `GATE1_FAILED`/`GATE1_COMPLETE` | 区分可修复 vs 致命失败 | verification-before-completion 内置此区分 |
164
- | `GATE2_RUNNING` | Security Scan 集成 | `cso` (gstack) Phase 1-6 安全审计替代 |
165
- | `SEALED_CODE_ISOLATION` | freeze 技术隔离 | **保留 freeze skill 调用** |
166
- | `MOBILE_TDD_EXECUTION` | React Native/Flutter 特定 TDD 执行 | 根据 `--type` 参数选择: mobile-react-native → RN TDD, mobile-flutter → Flutter TDD |
25
+ ### Gate 5a-BLOCK: 新增文件测试强制
167
26
 
168
- ---
27
+ - **新增 `.ts/.tsx` 文件**必须有对应的测试文件(`*.test.ts`、`*.spec.ts`、`__tests__/` 目录),否则 **BLOCK** 提交
28
+ - **修改已有文件**仅触发 WARNING(不阻断)
29
+ - **Escape valve**: 非 main/master 分支可设置 `SKIP_GATE_5A_BLOCK=1` 跳过阻断(仅 WARNING)
169
30
 
170
- ## Skill 间数据流契约
31
+ ### Gate M2: Mock 密度阈值调整
171
32
 
172
- | 步骤 | Skill | 输入 | 输出 | 失败回退 |
173
- |------|-------|------|------|----------|
174
- | 0a | dispatching-parallel-agents | specification.yaml + 任务分解 | 并行子任务分发 | 降级为串行 |
175
- | 0b | executing-plans | 子任务计划 | 实现 + review checkpoint | BLOCK |
176
- | 1 | test-driven-development | 需求描述 + 现有代码上下文 | 测试 + 代码 (RED→GREEN→REFACTOR) | 修复 max 3 次 → BLOCK |
177
- | 1.5 | vercel-react-native-skills | 项目类型 (mobile-react-native 或 mobile-flutter), package.json | RN/Flutter 测试执行结果 | RN/Flutter 测试失败 → 修复 max 3 次 → BLOCK |
178
- | 2 | freeze | 业务代码文件路径 | 锁定状态确认 | ❌ BLOCK |
179
- | 3 | requesting-code-review | 需求 + 测试 + 测试结果(**不传业务代码**) | review findings | 继续(记录 findings) |
180
- | 4 | unfreeze | 业务代码文件路径 | 解锁状态确认 | ❌ BLOCK |
181
- | 5 | verification-before-completion | 测试执行结果 | pass/fail 证据 | 修复 max 3 次 → BLOCK |
33
+ - Mock 密度阈值从 50% 降低至 **30%**
34
+ - **Phase 1**: WARNING 模式(仅告警,不阻断)
35
+ - **Phase 2**: 将在基线分析后启用 BLOCK 模式
36
+ - 可通过 `.mockpolicyrc` 配置阈值和行为
182
37
 
183
- ---
184
-
185
- ## 暂停点
38
+ ### Escape Valve
186
39
 
187
- | 暂停点 | 触发条件 | 用户操作 |
188
- |--------|---------|---------|
189
- | 验证 max 3 失败 | verification-before-completion 失败超过 3 次 | 用户决定修复或放弃 |
190
- | 成本超阈值 | 单任务 >$0.15 或日 >$1.00 | 用户决定继续或暂停 |
191
- | RN/Flutter 测试失败 | mobile-react-native 或 mobile-flutter 项目的测试执行失败且自动修复 max 3 次后仍未通过 | 用户决定继续修复或调整方案 |
192
-
193
- ---
194
-
195
- ## 输出
196
-
197
- - MVP v1 (`mvp-v1/` 目录)
198
- - 进入 Phase 3 自动执行
40
+ ```bash
41
+ # 非 main/master 分支临时跳过 Gate 5a-BLOCK
42
+ SKIP_GATE_5A_BLOCK=1 git commit -m "message"
43
+ ```
@@ -4,6 +4,8 @@
4
4
 
5
5
  多专家代码走查、测试对齐、浏览器测试。确保 MVP 符合 specification。
6
6
 
7
+ **执行者**: orchestrator 直接执行全部步骤(非 subagent dispatch)— Issue #249。
8
+
7
9
  Web 前端项目额外增加:系统化 QA、视觉审计、性能基线。
8
10
 
9
11
  ---
@@ -46,7 +48,7 @@ delphi code-walkthrough 执行:
46
48
  - ≥90% 共识 + APPROVED 才通过
47
49
 
48
50
  **如果 REQUEST_CHANGES**:
49
- - ⚠️ 暂停等待用户修复 Critical Issues + 处理 Major Concerns
51
+ - ⚠️ 暂停等待用户处理 Critical Issues + Major Concerns(orchestrator 直接执行,可交互)
50
52
  - 修复后回到 Round 2 重新评审
51
53
 
52
54
  **如果 APPROVED**: