singularity-forge/docs/zh-CN/user-docs/parallel-orchestration.md

311 lines
12 KiB
Markdown
Raw Normal View History

# 并行 Milestone 编排
在隔离的 git worktrees 中同时运行多个 milestones。每个 milestone 都拥有自己的 worker 进程、自己的分支和自己的上下文窗口;同时还会有一个 coordinator 跟踪进度、执行预算限制并保持整体同步。
> **状态:** 该功能默认处于 `parallel.enabled: false`。属于显式 opt-in对现有用户零影响。
## 快速开始
1. 在偏好设置中开启并行模式:
```yaml
---
parallel:
enabled: true
max_workers: 2
---
```
2. 启动并行执行:
```
/sf parallel start
```
SF 会扫描所有 milestones检查依赖与文件重叠给出一份可并行性报告并为符合条件的 milestones 启动 workers。
3. 监控进度:
```
/sf parallel status
```
4. 完成后停止:
```
/sf parallel stop
```
## 工作原理
### 架构
```
┌─────────────────────────────────────────────────────────┐
│ Coordinator你的 SF 会话) │
│ │
│ 职责: │
│ - 可并行性分析(依赖 + 文件重叠) │
│ - Worker 启动与生命周期管理 │
│ - 全部 workers 的预算跟踪 │
│ - 派发控制信号pause / resume / stop
│ - 会话状态监控 │
│ - Merge 对账 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Worker 1 │ │ Worker 2 │ │ Worker 3 │ ... │
│ │ M001 │ │ M003 │ │ M005 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ .sf/worktrees/ .sf/worktrees/ .sf/worktrees/ │
│ M001/ M003/ M005/ │
│ (milestone/ (milestone/ (milestone/ │
│ M001 branch) M003 branch) M005 branch) │
└─────────────────────────────────────────────────────────┘
```
### Worker 隔离
每个 worker 都是一个完全隔离的独立 `sf` 进程:
| 资源 | 隔离方式 |
|------|----------|
| **文件系统** | Git worktree每个 worker 都有自己的 checkout |
| **Git 分支** | `milestone/<MID>`:每个 milestone 一条分支 |
| **状态推导** | 通过 `SF_MILESTONE_LOCK` 环境变量,让 `deriveState()` 只看到被分配的 milestone |
| **上下文窗口** | 独立进程:每个 worker 都有自己的 agent sessions |
| **指标** | 每个 worktree 都有自己的 `.sf/metrics.json` |
| **崩溃恢复** | 每个 worktree 都有自己的 `.sf/auto.lock` |
### 协调方式
Workers 和 coordinator 通过基于文件的 IPC 通信:
- **会话状态文件**`.sf/parallel/<MID>.status.json`worker 写入 heartbeatcoordinator 读取
- **信号文件**`.sf/parallel/<MID>.signal.json`coordinator 写信号worker 消费
- **原子写入**:使用写临时文件再 rename 的方式,避免读到半成品
## 可并行性分析
在真正启动并行执行之前SF 会先检查哪些 milestones 可以安全并发运行。
### 规则
1. **未完成**:已完成的 milestones 会被跳过
2. **依赖满足**:所有 `dependsOn` 指向的 milestones 都必须已处于 `complete`
3. **文件重叠检查**:如果多个 milestones 会触碰同一批文件,会给出警告(但仍可执行)
### 示例报告
```
# Parallel Eligibility Report
## Eligible for Parallel Execution (2)
- **M002** — Auth System
All dependencies satisfied.
- **M003** — Dashboard UI
All dependencies satisfied.
## Ineligible (2)
- **M001** — Core Types
Already complete.
- **M004** — API Integration
Blocked by incomplete dependencies: M002.
## File Overlap Warnings (1)
- **M002** <-> **M003** — 2 shared file(s):
- `src/types.ts`
- `src/middleware.ts`
```
文件重叠只是警告,不是阻断条件。因为两个 milestones 会运行在各自独立的 worktree 中,它们不会在文件系统层面互相干扰。真正的冲突会在 merge 阶段被检测和处理。
## 配置
把下面内容加到 `~/.sf/PREFERENCES.md``.sf/PREFERENCES.md`
```yaml
---
parallel:
enabled: false # 总开关默认false
max_workers: 2 # 并发 workers 数1-4默认2
budget_ceiling: 50.00 # 聚合成本上限(美元,可选)
merge_strategy: "per-milestone" # 何时 merge"per-slice" 或 "per-milestone"
auto_merge: "confirm" # "auto"、"confirm" 或 "manual"
---
```
### 配置参考
| Key | 类型 | 默认值 | 说明 |
|-----|------|--------|------|
| `enabled` | boolean | `false` | 总开关。只有设为 `true``/sf parallel` 命令才可用。 |
| `max_workers` | number1-4 | `2` | 最大并发 worker 进程数。值越高,内存与 API 预算消耗也越高。 |
| `budget_ceiling` | number | 无 | 所有 workers 的聚合美元预算上限。达到后不会再派发新单元。 |
| `merge_strategy` | `"per-slice"``"per-milestone"` | `"per-milestone"` | worktree 变更何时回合并到主分支。Per-milestone 会等整个 milestone 完成后再合并。 |
| `auto_merge` | `"auto"``"confirm"``"manual"` | `"confirm"` | merge-back 策略。`confirm` 会在合并前询问;`manual` 要求显式执行 `/sf parallel merge`。 |
## 命令
| 命令 | 说明 |
|------|------|
| `/sf parallel start` | 分析可并行性、确认并启动 workers |
| `/sf parallel status` | 显示所有 workers 的状态、已完成单元和成本 |
| `/sf parallel stop` | 停止所有 workers发送 SIGTERM |
| `/sf parallel stop M002` | 停止某个指定 milestone 的 worker |
| `/sf parallel pause` | 暂停所有 workers完成当前单元后等待 |
| `/sf parallel pause M002` | 暂停某个指定 worker |
| `/sf parallel resume` | 恢复所有已暂停 workers |
| `/sf parallel resume M002` | 恢复某个指定 worker |
| `/sf parallel merge` | 把所有已完成 milestones 合并回 main |
| `/sf parallel merge M002` | 只把某个指定 milestone 合并回 main |
## 信号生命周期
Coordinator 通过信号和 workers 通信:
```
Coordinator Worker
│ │
├── sendSignal("pause") ──→ │
│ ├── consumeSignal()
│ ├── pauseAuto()
│ │ (完成当前单元后等待)
│ │
├── sendSignal("resume") ─→ │
│ ├── consumeSignal()
│ ├── 继续 dispatch loop
│ │
├── sendSignal("stop") ───→ │
│ + SIGTERM ────────────→ │
│ ├── consumeSignal() or SIGTERM handler
│ ├── stopAuto()
│ └── 进程退出
```
Workers 会在单元之间检查信号(位于 `handleAgentEnd`)。在 stop 场景下coordinator 还会额外发送 `SIGTERM` 来提高响应速度。
## Merge 对账
当 milestones 完成后,它们在 worktree 中的改动需要 merge 回主分支。
### Merge 顺序
- **顺序合并**(默认):按 milestone ID 顺序合并M001 在 M002 之前)
- **按完成顺序合并**:按照 milestones 实际完成的先后顺序合并
### 冲突处理
1. `.sf/` 状态文件(如 `STATE.md``metrics.json`)会**自动解决**,默认接受 milestone 分支版本
2. 代码冲突则会**停止并报告**。合并会暂停,并显示哪些文件冲突。你需要手动解决后,再执行 `/sf parallel merge <MID>` 重试
### 示例
```
/sf parallel merge
# Merge Results
- **M002** — merged successfully (pushed)
- **M003** — CONFLICT (2 file(s)):
- `src/types.ts`
- `src/middleware.ts`
Resolve conflicts manually and run `/sf parallel merge M003` to retry.
```
## 预算管理
当设置了 `budget_ceiling`coordinator 会跟踪所有 workers 的聚合成本:
- 成本会从每个 worker 的 session status 中汇总
- 达到上限后coordinator 会向 workers 发出停止信号
- 每个 worker 仍会独立遵守项目级 `budget_ceiling` 偏好
## 健康监控
### Doctor 集成
`/sf doctor` 能检测并行会话相关问题:
- **过期的并行会话**worker 进程已经死亡但没有清理干净。Doctor 会检查 `.sf/parallel/*.status.json` 中记录的 PID 和 heartbeat发现失效后自动清理。
可以执行 `/sf doctor --fix` 自动清理。
### 过期检测
满足以下任一条件时,会话会被视为 stale
- Worker PID 已经不存在(通过 `process.kill(pid, 0)` 检查)
- 最近一次 heartbeat 超过 30 秒
Coordinator 会在 `refreshWorkerStatuses()` 中执行 stale detection并自动移除已经死亡的会话。
## 安全模型
| 安全层 | 保护内容 |
|--------|----------|
| **Feature flag** | 默认 `parallel.enabled: false`,不影响现有用户 |
| **可并行性分析** | 启动前检查依赖和文件重叠 |
| **Worker 隔离** | 独立进程、worktrees、分支、上下文窗口 |
| **`SF_MILESTONE_LOCK`** | 每个 worker 在状态推导时只能看到自己的 milestone |
| **`SF_PARALLEL_WORKER`** | Worker 不能再嵌套启动新的并行会话 |
| **预算上限** | 跨所有 workers 执行聚合成本限制 |
| **信号式关闭** | 通过文件信号 + SIGTERM 优雅停止 |
| **Doctor 集成** | 检测并清理孤儿会话 |
| **冲突感知 merge** | 遇到代码冲突时停止;`.sf/` 状态冲突自动解决 |
## 文件布局
```
.sf/
├── parallel/ # Coordinator ↔ worker IPC
│ ├── M002.status.json # Worker heartbeat + progress
│ ├── M002.signal.json # Coordinator → worker signals
│ ├── M003.status.json
│ └── M003.signal.json
├── worktrees/ # Git worktrees每个 milestone 一个)
│ ├── M002/ # M002 的隔离 checkout
│ │ ├── .sf/ # M002 自己的状态文件
│ │ │ ├── auto.lock
│ │ │ ├── metrics.json
│ │ │ └── milestones/
│ │ └── src/ # M002 的工作副本
│ └── M003/
│ └── ...
└── ...
```
`.sf/parallel/``.sf/worktrees/` 都会被 gitignore因为它们只是运行时协调文件永远不会提交。
## 故障排查
### “Parallel mode is not enabled”
在偏好设置里加入 `parallel.enabled: true`
### “No milestones are eligible for parallel execution”
说明所有 milestones 要么已完成,要么被依赖阻塞。可通过 `/sf queue` 查看 milestone 状态和依赖链。
### Worker 崩溃后如何恢复
Workers 会自动把状态持久化到磁盘。如果某个 worker 进程死亡coordinator 会通过 heartbeat 超时检测到死掉的 PID并把该 worker 标记为 crashed。重启后worker 会从磁盘状态继续崩溃恢复、worktree 重入和 completed-unit 跟踪都会延续之前的状态。
1. 执行 `/sf doctor --fix` 清理 stale sessions
2. 执行 `/sf parallel status` 查看当前状态
3. 重新执行 `/sf parallel start`,为剩余 milestones 启动新的 workers
### 并行执行完成后发生 merge 冲突
1. 执行 `/sf parallel merge` 查看哪些 milestones 存在冲突
2.`.sf/worktrees/<MID>/` 对应的 worktree 中手动解决冲突
3. 执行 `/sf parallel merge <MID>` 重试
### Workers 看起来卡住了
先检查是否触达了预算上限:`/sf parallel status` 会显示每个 worker 的成本。继续执行的话,提升 `parallel.budget_ceiling` 或直接移除它。