新增 Ralph PRD 用户指南(2026-04-11)

This commit is contained in:
2026-04-11 10:34:06 +08:00
parent 65dd98ee88
commit e2270427f0
2 changed files with 783 additions and 0 deletions

View File

@@ -0,0 +1,337 @@
# 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/`

View File

@@ -0,0 +1,446 @@
# PRD 模板 - 内容生产工作流(非编程任务)
> 基于 Ralph 模式改造,适用于视频制作、文章发布、研究分析等非编程任务。
---
## 📋 prd.json - 结构化任务清单
```json
{
"version": "1.0",
"projectName": "项目名称",
"projectType": "content-production | video | research | multi-step-task",
"created": "YYYY-MM-DD",
"description": "项目简要描述",
"userStories": [
{
"id": "1",
"title": "任务描述(动宾结构,越具体越好)",
"branchName": "feature/xxx",
"passes": false,
"assignedTo": "agentId 或 human",
"qualityGate": {
"type": "file-exists | command-output | human-review | llm-judge",
"description": "如何判断此任务完成",
"command": "(可选)验证命令",
"expected": "(可选)预期输出"
},
"notes": "执行过程中的备注/心得"
}
],
"qualityCheckCommands": {
"description": "项目级质量检查命令(非 story 级别)"
}
}
```
---
## ✅ Quality Gate 类型说明
| 类型 | 适用场景 | 判断方式 |
|------|---------|---------|
| `file-exists` | 文件生成类任务 | 检查文件是否生成 |
| `command-output` | 命令执行类 | 验证命令退出码或输出 |
| `human-review` | 创意/审核类 | 需要人工确认(不可完全消除) |
| `llm-judge` | 内容质量评估 | LLM 评估输出质量 |
---
## 📄 适用场景模板
### 场景 A视频制作
```json
{
"projectName": "AI 工具对比视频",
"projectType": "video",
"userStories": [
{
"id": "1",
"title": "撰写 3 分钟视频脚本AI 工具对比)",
"qualityGate": {"type": "file-exists", "description": "脚本文件存在且 > 500 字"},
"notes": ""
},
{
"id": "2",
"title": "收集/生成视频素材片段",
"qualityGate": {"type": "file-exists", "description": "素材文件夹存在且包含 > 3 个片段"},
"notes": ""
},
{
"id": "3",
"title": "FFmpeg 剪辑拼接成完整视频",
"qualityGate": {"type": "command-output", "description": "ffprobe 检查视频时长 3min±10s"},
"notes": ""
},
{
"id": "4",
"title": "生成封面图",
"qualityGate": {"type": "file-exists", "description": "封面图存在"},
"notes": ""
},
{
"id": "5",
"title": "上传到 B 站",
"qualityGate": {"type": "human-review", "description": "人工确认视频已发布"},
"notes": ""
}
]
}
```
### 场景 B文章发布公众号
```json
{
"projectName": "公众号文章 - AI 趋势分析",
"projectType": "content-production",
"userStories": [
{
"id": "1",
"title": "使用 Last30Days 研究 AI 趋势",
"qualityGate": {"type": "file-exists", "description": "生成的研究报告存在"},
"notes": ""
},
{
"id": "2",
"title": "生成摘要、金句、观点提炼",
"qualityGate": {"type": "command-output", "description": "输出包含摘要+3个以上金句"},
"notes": ""
},
{
"id": "3",
"title": "生成文章配图",
"qualityGate": {"type": "file-exists", "description": "配图文件存在"},
"notes": ""
},
{
"id": "4",
"title": "排版并预览HTML/Markdown",
"qualityGate": {"type": "human-review", "description": "人工预览确认格式无误"},
"notes": ""
},
{
"id": "5",
"title": "发布到公众号",
"qualityGate": {"type": "human-review", "description": "人工确认已群发"},
"notes": ""
}
]
}
```
### 场景 C竞品动态追踪
```json
{
"projectName": "竞品分析 - Cursor vs Windsurf",
"projectType": "research",
"userStories": [
{
"id": "1",
"title": "Last30Days 搜索两个竞品近 30 天动态",
"qualityGate": {"type": "file-exists", "description": "生成两个研究文件"},
"notes": ""
},
{
"id": "2",
"title": "抓取竞品官网更新页面",
"qualityGate": {"type": "file-exists", "description": "页面内容已保存"},
"notes": ""
},
{
"id": "3",
"title": "生成对比分析报告",
"qualityGate": {"type": "command-output", "description": "报告文件 > 1000 字"},
"notes": ""
},
{
"id": "4",
"title": "保存到 Obsidian 知识库",
"qualityGate": {"type": "file-exists", "description": "笔记存在于知识库"},
"notes": ""
}
]
}
```
---
## 🔄 Ralph 执行循环(简化版)
不使用 Claude Code 的情况下,可通过 OpenClaw sub-agent 模拟:
```
每次循环:
1. 读取 prd.json
2. 选取 id 最小的 passes:false 的 story
3. 生成 fresh sub-session 执行该 story
4. 运行 quality gate 检查
5. 通过 → passes:true追加 notes
6. 重复直到全部完成
```
---
## 📝 progress.txt 格式
```
[YYYY-MM-DD HH:mm] Story #N 完成: <title>
心得: <执行过程中的学到的东西>
耗时: <N 分钟>
---
```
---
## 💡 与编程任务 PRD 的核心区别
| 维度 | 编程任务 PRD | 非编程任务 PRD |
|------|------------|--------------|
| 工具链 | git, npm, typecheck, test | FFmpeg, 爬虫, LLM |
| 质量门 | 自动CI/CD | 混合(自动+人工) |
| 人工介入 | 极低(代码审查) | 中等(创意审核) |
| Story 大小 | 极小(单次完成) | 中等(可包含创意工作) |
| 迭代速度 | 快(机器执行) | 慢(人机混合) |
---
## 🦞 OpenClaw Native Ralph 架构2026-04-11 实测验证)
### 核心发现
| 问题 | 结论 |
|------|------|
| Ubuntu1 上无 skill0个 | Skill 密集型任务 → MacMini系统任务 → Ubuntu1 |
| sessions_spawn + node 参数 | ✅ 可跨节点派生子 agent |
| prd.json 状态机 | ✅ 落地验证通过 |
| progress.txt 追加日志 | ✅ 追加验证通过 |
| Gateway REST API | ❌ 未开启,改用 sessions_spawn |
### 架构图
```
星枢MacMini / 主会话)
└── Ralph EnginePython 脚本 / 星枢派生子 agent
├── 读取 prd.json
├── 选取 passes:false 的 story
├── 判断 targetNodeskill密集型 → MacMini / 系统任务 → Ubuntu1
├── sessions_spawn(mode=run, node=目标节点)
│ └── 子 agent 执行 story + quality gate
├── 更新 prd.json (passes:true / notes)
├── 追加 progress.txt
└── 循环直到全部完成 → Telegram 通知
```
### 节点 Skill 地图
| 节点 | Skill 可用性 | 适合任务类型 |
|------|------------|------------|
| MacMini (192.168.3.189) | 全部Last30Days, n8n, OpenCode, image_generate 等) | 研究、内容生产、编码 |
| Ubuntu1 (192.168.3.47) | 无 | 系统运维、Docker、巡检 |
| Ubuntu2 (192.168.3.45) | 部分 | n8n 工作流、中间层处理 |
### sessions_spawn 调用格式OpenClaw Native
```python
# Ralph Engine 内核心调用
sessions_spawn(
task=f"""你是 {node} 上的执行者。执行以下 story
Story: {story_title}
Quality Gate: {qg_type} - {qg_desc}
工作目录: {work_dir}
目标文件: {target_path}
步骤:
1. [执行命令]
2. [quality gate 验证]
3. [落地 marker 文件或输出]
""",
runtime="subagent",
mode="run",
node="ubuntu1 | (default MacMini)",
runTimeoutSeconds=600,
label=f"ralph-story-{story_id}"
)
```
### Quality Gate 落地标准(实测有效)
```python
# ✅ 有效类型
"type": "file-exists" # touch marker 文件
"type": "command-output" # 命令退出码 0
"type": "human-review" # 人工确认(不可省)
# ⚠️ 限制
# - Last30Days 等 skill 必须确认目标节点有装
# - human-review 类型需要人工发送确认指令
```
---
## 🦀 Ralph Engine 脚本Python
> 路径:`~/.openclaw/scripts/ralph_engine.py`
> 运行环境MacMini协调层
> 依赖OpenClaw sessions_spawn通过 API 或 CLI
```python
#!/usr/bin/env python3
"""
Ralph Engine - OpenClaw Native
Coordinator: MacMini
Execution: 按 story 分配到对应节点
PRD: ${WORK_DIR}/prd.json
Progress: ${WORK_DIR}/progress.txt
"""
import json, subprocess, time, sys
from datetime import datetime
WORK_DIR = sys.argv[1] if len(sys.argv) > 1 else "./ralph-test"
PRD_FILE = f"{WORK_DIR}/prd.json"
PROGRESS_FILE = f"{WORK_DIR}/progress.txt"
# Skill → Node 映射
NODE_MAP = {
"last30days": "macmini", # skill 密集型
"n8n": "ubuntu2",
"image_generate": "macmini",
"video_generate": "macmini",
"opencode": "macmini",
"docker": "ubuntu1", # 系统任务
"system": "ubuntu1",
"default": "macmini"
}
def get_node_for_story(story):
"""根据 story 内容判断执行节点"""
title = story.get("title", "").lower()
for key, node in NODE_MAP.items():
if key in title:
return node
return NODE_MAP["default"]
def spawn_story(story, work_dir):
"""通过 openclaw sessions CLI 派生子 agent"""
story_id = story["id"]
title = story["title"]
qg = story.get("qualityGate", {})
node = get_node_for_story(story)
prompt = f"""Task: {title}
Quality Gate: {qg.get('type')} - {qg.get('description', '')}
Work dir: {work_dir}
Output file: {qg.get('path', f'{work_dir}/story_{story_id}_out.txt')}
Steps:
1. Execute the task
2. Run quality gate check
3. Report PASS or FAIL with details
4. Create marker file if pass: touch {work_dir}/story_{story_id}_done
"""
# 调用 openclaw acp sessions 或者通过 CLI
cmd = [
"openclaw", "acp", "sessions",
"--session", f"ralph-{story_id}",
"--require-existing"
]
# 实际通过 sessions_spawn tool 调用,此处仅作架构说明
return True # placeholder
def main():
prd = json.load(open(PRD_FILE))
pending = [s for s in prd["userStories"] if not s.get("passes")]
for story in pending:
spawn_story(story, WORK_DIR)
# 更新 prd.json + progress.txt
print("Ralph complete")
if __name__ == "__main__":
main()
```
---
## ⏰ 自主循环触发设计
### 方式一Cron 触发(定时拉起 Ralph Engine
```bash
# MacMini crontab
0 2 * * * openclaw agent --task "检查 ~/ralph-queue/ 目录,有 prd.json 则启动 Ralph Engine" --agent xingshu
```
### 方式二:目录监听(文件触发)
```bash
# inotifywait 或 launchd WatchPath
# 检测到 ~/ralph-queue/*.json → 自动启动 Ralph Engine
```
### 方式三:用户指令触发(最简单)
```
比利哥:开始执行 ralph prd.json
星枢 → 派生子 agent → 启动 Engine
```
---
## 📁 标准目录结构
```
~/ralph/
├── queue/ # 待执行的 prd.json 放这里
├── active/ # 正在执行的项目
├── archive/ # 完成的项目归档
│ └── YYYY-MM-DD-projectName/
│ ├── prd.json
│ ├── progress.txt
│ └── [outputs...]
└── ralph_engine.py # 执行引擎
```
---
## ✅ 实测验证记录2026-04-11
### 测试Ubuntu1 系统巡检
- **结果**3/3 stories ✅ 完成
- **落地文件**`sysinfo.txt`(1116B), `docker_status.txt`(835B), `audit_report.md`(2347B), `prd.json`(345B ✅ passes:true), `progress.txt`(188B ✅ 3条追加)
- **耗时**1分43秒
### 关键验证点
| 验证项 | 结果 |
|--------|------|
| prd.json passes:true 更新 | ✅ 成功 |
| progress.txt 追加日志 | ✅ 成功 |
| 跨节点 sessions_spawn | ✅ Ubuntu1 正常 |
| skill 路径Last30Days | ⚠️ Ubuntu1 无 skill改用模拟 |
| 文件落地 | ✅ 实际验证 |
### 架构修正(对比原设计)
1. **Python Ralph Engine 无法直接调用 sessions API** → 改用 "Ralph Engine as sub-agent task"
2. **skill 全在 MacMini** → 任务智能路由系统任务→Ubuntu1/内容生产→MacMini
3. **Gateway REST API 限制** → sessions_spawn 是运行时工具,非 API
### 最终架构(已验证)
```
用户/星枢主会话
└── sessions_spawn → Ralph Engine sub-agent
├── 读取 prd.json
├── exec 执行 storynode 本地)
├── quality gate 检查
├── 更新 prd.json + progress.txt
└── 循环 → 完成后通知
```