# Ralph PRD 创建与执行指南

> 如何用 prd.json 描述一个多步骤任务，让星枢自动跑完。

---

## 📋 一分钟速览

```
1.  创建 prd.json（按本指南格式）
2.  放进 ~/ralph/queue/ 目录
3.  告诉星枢：「执行这个 PRD」
4.  星枢派 Ralph Engine 子 agent 自动跑完
5.  完成 → Telegram 收到报告
```

---

## 📁 PRD 文件格式

```json
{
  "projectName": "项目名称（中文）",
  "projectType": "任务类型",
  "created": "YYYY-MM-DD",
  "description": "项目简要描述",
  "workDir": "执行时的工作目录（绝对路径）",
  "maxIterations": 10,
  "userStories": [
    {
      "id": "1",
      "title": "任务描述（动宾结构，越具体越好）",
      "passes": false,
      "qualityGate": {
        "type": "quality gate 类型",
        "description": "如何判断完成",
        "command": "验证命令（可选）",
        "path": "期望文件路径（可选）"
      },
      "notes": "执行备注（留空）"
    }
  ]
}
```

---

## 🎯 Quality Gate 类型说明

设计 quality gate 是 PRD 中最关键的一步。gate 决定了子 agent 如何判断 story 完成。

| 类型 | 适用场景 | 设计方法 |
|------|---------|---------|
| `file-exists` | 文件生成类任务 | 指定期望生成的文件路径 |
| `command-output` | 命令执行类 | 指定命令和期望输出片段 |
| `human-review` | 创意/审核类 | 指定需要人工确认的环节 |

### 设计原则

**好的 quality gate 示例：**
```json
{"type": "file-exists", "path": "/Users/weishen/ralph/output/report.md"}
{"type": "command-output", "command": "wc -w /tmp/draft.md | awk '{print $1}'", "expected": "500"}
{"type": "command-output", "command": "test -f /tmp/cover.png && echo OK", "expected": "OK"}
```

**❌ 差的 quality gate（无法判断）：**
```json
{"type": "file-exists", "description": "生成报告"}
```
没有具体文件路径，引擎无法验证。

---

## 🛠️ 四步创建 PRD

### Step 1：确定项目类型

| 类型 | 适用场景 | 示例 |
|------|---------|------|
| `research` | 信息收集、分析 | 竞品分析、市场调研 |
| `content-production` | 内容创作 | 公众号文章、视频脚本 |
| `video` | 视频制作 | B站视频、教程 |
| `system-audit` | 系统巡检、维护 | 服务器检查、日志分析 |
| `multi-step-task` | 通用多步骤任务 | 任何包含多个阶段的工作 |

### Step 2：拆解 Stories

**每个 story 必须满足：**
- 能在单次 LLM 调用中完成
- 有明确的输出物（文件或命令结果）
- quality gate 可以被自动化验证

**拆解检查清单：**
- [ ] story 描述是一个具体的「动作+结果」
- [ ] 有明确的 quality gate 验证方式
- [ ] 不依赖其他 story 的输出（解耦）
- [ ] 大小适中（避免「完成整个项目」这种过大的 story）

**好 story vs 差 story：**

| 差 ❌ | 好 ✅ |
|-------|-------|
| 完成内容营销策略 | 使用 Last30Days 研究竞品近30天动态 |
| 写一篇文章 | 生成 1500 字公众号文章草稿，保存到 draft.md |
| 做视频 | 用 FFmpeg 将3个素材片段拼接成 3 分钟视频 |

### Step 3：填写 quality gate

每个 story 必须设计 quality gate：

```json
{
  "id": "1",
  "title": "使用 Last30Days 研究竞品动态",
  "qualityGate": {
    "type": "file-exists",
    "description": "确认研究数据文件已生成",
    "path": "/Users/weishen/ralph/active/campaign/research.md"
  }
}
```

### Step 4：创建文件

在 `~/ralph/queue/` 创建 `prd.json`：

```bash
mkdir -p ~/ralph/queue
# 用编辑器创建 prd.json，或让星枢帮你创建
```

---

## 📝 PRD 示例

### 示例 A：公众号文章生产

```json
{
  "projectName": "AI 工具对比文章",
  "projectType": "content-production",
  "created": "2026-04-11",
  "workDir": "/Users/weishen/ralph/active/ai-tools-article",
  "maxIterations": 8,
  "userStories": [
    {
      "id": "1",
      "title": "使用 Last30Days 研究 Cursor 和 Windsurf 近30天热点",
      "passes": false,
      "qualityGate": {
        "type": "file-exists",
        "description": "确认生成了原始数据文件",
        "path": "/Users/weishen/ralph/active/ai-tools-article/raw_research.md"
      },
      "notes": ""
    },
    {
      "id": "2",
      "title": "生成文章大纲（标题/小标题/金句）",
      "passes": false,
      "qualityGate": {
        "type": "file-exists",
        "description": "确认大纲文件存在",
        "path": "/Users/weishen/ralph/active/ai-tools-article/outline.md"
      },
      "notes": ""
    },
    {
      "id": "3",
      "title": "撰写完整文章（1500字）",
      "passes": false,
      "qualityGate": {
        "type": "command-output",
        "description": "字数 >= 1200",
        "command": "wc -w /Users/weishen/ralph/active/ai-tools-article/article.md | awk '{print $1}'",
        "expected": "1"
      },
      "notes": ""
    },
    {
      "id": "4",
      "title": "生成文章配图",
      "passes": false,
      "qualityGate": {
        "type": "file-exists",
        "description": "确认封面图生成",
        "path": "/Users/weishen/ralph/active/ai-tools-article/cover.png"
      },
      "notes": ""
    },
    {
      "id": "5",
      "title": "人工预览确认（发布前审核）",
      "passes": false,
      "qualityGate": {
        "type": "human-review",
        "description": "人工预览文章，确认无误后手动告知星枢继续",
        "notes": ""
      }
    }
  ]
}
```

### 示例 B：竞品分析研究

```json
{
  "projectName": "Cursor vs Windsurf 竞品分析",
  "projectType": "research",
  "created": "2026-04-11",
  "workDir": "/Users/weishen/ralph/active/cursor-vs-windsurf",
  "maxIterations": 6,
  "userStories": [
    {
      "id": "1",
      "title": "Last30Days 搜索 Cursor 近30天热点",
      "passes": false,
      "qualityGate": {
        "type": "file-exists",
        "path": "/Users/weishen/ralph/active/cursor-vs-windsurf/cursor_research.md"
      },
      "notes": ""
    },
    {
      "id": "2",
      "title": "Last30Days 搜索 Windsurf 近30天热点",
      "passes": false,
      "qualityGate": {
        "type": "file-exists",
        "path": "/Users/weishen/ralph/active/cursor-vs-windsurf/windsurf_research.md"
      },
      "notes": ""
    },
    {
      "id": "3",
      "title": "抓取两个竞品的官网更新",
      "passes": false,
      "qualityGate": {
        "type": "file-exists",
        "path": "/Users/weishen/ralph/active/cursor-vs-windsurf/official_updates.md"
      },
      "notes": ""
    },
    {
      "id": "4",
      "title": "生成对比分析报告",
      "passes": false,
      "qualityGate": {
        "type": "command-output",
        "description": "报告 >= 1000 字",
        "command": "wc -w /Users/weishen/ralph/active/cursor-vs-windsurf/analysis_report.md | awk '{print $1}'",
        "expected": "1"
      },
      "notes": ""
    },
    {
      "id": "5",
      "title": "保存到 Obsidian 知识库",
      "passes": false,
      "qualityGate": {
        "type": "file-exists",
        "path": "/Users/weishen/Workspace/nexus/openclaw/knowledgebase/research/cursor-vs-windsurf-2026-04.md"
      },
      "notes": ""
    }
  ]
}
```

---

## 🚀 执行与追踪

### 提交 PRD 执行

```bash
# 把 PRD 放进队列
mv ~/Downloads/my-prd.json ~/ralph/queue/

# 告诉星枢：
# 「执行 ~/ralph/queue/my-prd.json」
```

### 查看执行状态

```bash
# 查看所有项目的状态
ls -la ~/ralph/active/

# 查看某个项目的 prd.json 状态
cat ~/ralph/active/my-project/prd.json

# 查看执行日志
cat ~/ralph/active/my-project/progress.txt
```

### 目录结构说明

| 目录 | 用途 |
|------|------|
| `~/ralph/queue/` | PRD 入口，放入待执行的项目 |
| `~/ralph/active/` | 正在执行的项目（从 queue 移入） |
| `~/ralph/archive/` | 已完成项目归档 |

### human-review 类型的处理

当遇到 `human-review` 类型 story：
1. 子 agent 会暂停并等待
2. 你手动检查输出物
3. 告诉星枢：「Story #N 可以继续」
4. 星枢更新 prd.json 继续执行

---

## ⚠️ 常见问题

**Q: story 太长做不完怎么办？**
A: 拆小。每个 story 应该在 5 分钟内完成。

**Q: quality gate 判断失败怎么办？**
A: 检查 `progress.txt` 看失败原因，修复问题后告诉星枢「重试 Story #N」。

**Q: Ubuntu1 和 MacMini 怎么选执行节点？**
A: 内容生产（Last30Days、图片生成、n8n）→ MacMini；系统运维（Docker、巡检）→ Ubuntu1。

**Q: 任务中途可以暂停吗？**
A: 可以。直接告诉星枢「暂停」，prd.json 会保留当前状态。

---

## 📂 相关文件

- 模板：`openclaw/knowledgebase/prd/TEMPLATE.md`
- 技术实现：`~/.openclaw/scripts/ralph_engine.py`
- 知识库目录：`openclaw/knowledgebase/prd/`
