Update nexus: fix conflicts and sync local changes
This commit is contained in:
@@ -1,446 +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 上无 skill(0个) | Skill 密集型任务 → MacMini;系统任务 → Ubuntu1 |
|
||||
| sessions_spawn + node 参数 | ✅ 可跨节点派生子 agent |
|
||||
| prd.json 状态机 | ✅ 落地验证通过 |
|
||||
| progress.txt 追加日志 | ✅ 追加验证通过 |
|
||||
| Gateway REST API | ❌ 未开启,改用 sessions_spawn |
|
||||
|
||||
### 架构图
|
||||
|
||||
```
|
||||
星枢(MacMini / 主会话)
|
||||
└── Ralph Engine(Python 脚本 / 星枢派生子 agent)
|
||||
│
|
||||
├── 读取 prd.json
|
||||
├── 选取 passes:false 的 story
|
||||
├── 判断 targetNode:skill密集型 → 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 执行 story(node 本地)
|
||||
├── quality gate 检查
|
||||
├── 更新 prd.json + progress.txt
|
||||
└── 循环 → 完成后通知
|
||||
```
|
||||
# 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 上无 skill(0个) | Skill 密集型任务 → MacMini;系统任务 → Ubuntu1 |
|
||||
| sessions_spawn + node 参数 | ✅ 可跨节点派生子 agent |
|
||||
| prd.json 状态机 | ✅ 落地验证通过 |
|
||||
| progress.txt 追加日志 | ✅ 追加验证通过 |
|
||||
| Gateway REST API | ❌ 未开启,改用 sessions_spawn |
|
||||
|
||||
### 架构图
|
||||
|
||||
```
|
||||
星枢(MacMini / 主会话)
|
||||
└── Ralph Engine(Python 脚本 / 星枢派生子 agent)
|
||||
│
|
||||
├── 读取 prd.json
|
||||
├── 选取 passes:false 的 story
|
||||
├── 判断 targetNode:skill密集型 → 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 执行 story(node 本地)
|
||||
├── quality gate 检查
|
||||
├── 更新 prd.json + progress.txt
|
||||
└── 循环 → 完成后通知
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user