持久完成循环:Ralph 单任务迭代与完成审计
持久完成循环:Ralph 单任务迭代与完成审计
学习目标
- 理解 Ralph 循环的迭代步骤和状态流转
- 掌握完成审计的三层检查(存在性 → 通过判定 → 检查清单与证据)
- 了解视觉门控和 Deslop 清理的具体实现
- 理解 Ralph 与 Ultragoal 的组成关系
前置知识
本章涉及持久完成循环的通用原理,建议先阅读:
下文假设你已理解上述概念,直接聚焦 Oh-My-Codex 的具体实现。
项目实践
Ralph 循环的迭代步骤
Ralph 的 SKILL.md 定义了编号的步骤序列:
Step 0: 上下文快照 → .omx/context/{task-slug}-{timestamp}.mdStep 1: 进度回顾(从上次迭代状态)Step 2: 继续执行Step 3: 并行委托给专业 Agent(agent_type: "architect" 等)Step 4: 后台运行耗时操作Step 5: 视觉门控(视觉任务时截图评分 ≥ 90)Step 6: 验证完成(测试、构建、lint、无待办 TODO)Step 7: 架构师验证(spawn architect 子 Agent)Step 7.5: Deslop 清理(运行 ai-slop-cleaner)Step 7.6: 回归验证(重新运行测试)Step 8: 审计通过 → update_goal(complete) + /cancelStep 9: 审计不通过 → 修复并重试状态管理(通过 omx state write/read/clear):
伪代码(Ralph 状态 schema):{ "mode": "ralph", "active": true, "iteration": 1, "max_iterations": 10, "current_phase": "executing", // starting | executing | verifying | fixing | blocked_on_user | complete | failed | cancelled "started_at": "2026-06-05T...", "completed_at": null, "completion_audit": { "passed": true, "prompt_to_artifact_checklist": [...], "verification_evidence": [...] }}完成审计的三层检查
伪代码(src/ralph/completion-audit.ts — evaluateRalphCompletionAuditEvidence):function evaluateRalphCompletionAuditEvidence(state): // 层1: 审计存在性 audit = null if state.completion_audit: audit = state.completion_audit else if state.completion_audit_path: path = resolvePath(state.completion_audit_path, workspace) if not isWithinWorkspace(path): return { complete: false, reason: "Path traversal detected" } if not isValidJsonFile(path): return { complete: false, reason: "missing_completion_audit" } audit = readJsonFile(path)
if not audit: return { complete: false, reason: "missing_completion_audit" }
// 层2: 通过判定(严格布尔值) if audit.passed !== true: return { complete: false, reason: "completion_audit_not_passing" }
// 层3: 检查清单与证据 checklist = audit.prompt_to_artifact_checklist || audit.promptToArtifactChecklist || audit.checklist
evidence = audit.verification_evidence || audit.verificationEvidence || audit.evidence
if not checklist or checklist.length == 0: return { complete: false, reason: "missing_completion_checklist" } if not evidence or evidence.length == 0: return { complete: false, reason: "missing_verification_evidence" }
return { complete: true }字段别名兼容:审计支持多种字段名变体(prompt_to_artifact_checklist、promptToArtifactChecklist、checklist),以兼容不同版本的产出格式。
视觉门控
对于视觉相关任务(如 UI 变更),Ralph 要求截图评分 ≥ 90:
伪代码:function evaluateVisualVerdict(entries): visualEntries = entries.filter(e => e.type == "visual_feedback") if visualEntries.length == 0: return { passed: true, reason: "No visual tasks" } // 非视觉任务跳过
latestScore = visualEntries.last.score if latestScore >= 90: return { passed: true, reason: `Visual score ${latestScore} >= 90` }
return { passed: false, reason: `Visual score ${latestScore} < 90, need improvement` }视觉反馈记录在 .omx/state/{scope}/ralph-progress.json 的 visual_feedback[] 数组中。
Deslop 清理(Step 7.5)
伪代码:function runDeslopPass(changedFiles): // 运行 AI Slop Cleaner 技能 result = runSkill("ai-slop-cleaner", { files: changedFiles })
// 清理典型的 AI 冗余模式: // - 重复的防御性代码 // - 过度的注释和文档 // - 未使用的导入和变量 // - 多余的错误处理链
return { status: result.status, cleanedFiles: result.cleanedFiles, linesRemoved: result.linesRemoved }为什么 Deslop 在架构师验证之后:架构师需要看到”完整”的代码(包括冗余部分)来评估架构完整性。Deslop 清理后必须重新验证,因为清理可能改变代码行为。
回归验证(Step 7.6)
伪代码:function runRegressionVerification(deslopResult): // 重新运行所有测试 testResult = runTests() buildResult = runBuild() lintResult = runLint()
if not testResult.passed: return { passed: false, reason: `Tests failed after deslop: ${testResult.failures}` } if not buildResult.passed: return { passed: false, reason: `Build failed after deslop` } if not lintResult.passed: return { passed: false, reason: `Lint failed after deslop` }
return { passed: true }与 Codex 目标的集成
伪代码(Ralph 循环中的目标集成):async function runRalphLoop(objective): // Step 0: 获取目标 goal = await codexTools.get_goal() goal.objective = objective // 绑定接受范围
iteration = 0 while iteration < max_iterations: iteration++
// Steps 1-7.6: 执行循环 result = executeRalphSteps()
// 完成审计 audit = evaluateRalphCompletionAuditEvidence(result.state)
if audit.complete: // 审计通过 → 完成目标 await codexTools.update_goal({ status: "complete" }) await runCommand("/cancel") return { status: "complete", iterations: iteration }
// 审计不通过 → 修复并重试 result.state.current_phase = "fixing" result.state.iteration = iteration
return { status: "max_iterations_exceeded", iterations: iteration }Ralph 与 Ultragoal 的组成关系
| 场景 | 使用方式 |
|---|---|
| 单任务需要多次迭代 | 直接使用 Ralph |
| 多目标项目中的某个故事需要迭代 | Ultragoal 故事 → Ralph 执行 |
| 整个项目需要多目标拆解 | 直接使用 Ultragoal |
组合模式:
Ultragoal 故事 G003 "实现缓存层" └→ Ralph 循环执行 "实现缓存层" ├→ 迭代1: 初版实现 → 审计不通过(测试失败) ├→ 迭代2: 修复测试 → 审计不通过(架构师未签字) ├→ 迭代3: 架构调整 → 审计通过 └→ G003 标记为 complete └→ Ultragoal 调度器进入 G004进度账本
伪代码(ralph-progress.json):{ "schema_version": 1, "source": "ralph", "source_sha256": "abc123...", "strategy": "persistence-loop", "created_at": "2026-06-05T...", "updated_at": "2026-06-05T...", "entries": [ { "iteration": 1, "phase": "executing", "summary": "Implemented cache layer with LRU eviction" }, { "iteration": 2, "phase": "verifying", "summary": "Fixed test failures, awaiting architect review" } ], "visual_feedback": [ { "iteration": 1, "score": 85, "screenshot_url": ".omx/context/visual-001.png" } ]}状态转换验证
伪代码(src/ralph/contract.ts — validateAndNormalizeRalphState):function validateAndNormalizeRalphState(rawState): state = normalizeTimestamps(rawState)
// 终态必须 active=false if state.current_phase in TERMINAL_PHASES: state.active = false if not state.completed_at: state.completed_at = now()
// 验证 ISO 时间戳 assertValidISO(state.started_at) if state.completed_at: assertValidISO(state.completed_at)
// 验证相位转换合法性 assertValidPhaseTransition(state.current_phase, state.previous_phase)
return state问题与规避
| 问题 | 后果 | OMX 的规避策略 |
|---|---|---|
| 循环无上限 | 无限循环消耗资源 | max_iterations 限制,超限后标记为 failed |
| 完成审计伪造 | Agent 自行声称通过 | 三层检查:存在性 → 布尔判定 → 证据验证 |
| Deslop 过度清理 | 合法代码被误删 | Deslop 只清除明确的 AI 冗余模式 |
| 回归验证遗漏 | Deslop 后新 bug 未被发现 | 回归验证必须重新运行所有测试 |
| 视觉门控边界情况 | 分数 89 vs 90 的争议 | 阈值可配置,根据任务类型调整 |
设计取舍
为什么 Ralph 选择迭代循环而非一次性完成?
Ralph 的核心承诺是”不停止直到完成”,而非”一次做好”。
优势:
- 容错性:第一次实现有 bug 时自动修复
- 质量保障:完成审计确保每次完成都是经过验证的
- 透明性:进度账本记录每次迭代的进展
代价:
- 成本:每次迭代都需要模型调用
- 延迟:完整的 Ralph 循环(8+ 步骤)比单次执行慢得多
- 不适合简单任务:小任务使用 Ralph 是过度工程
何时使用 Ralph:
- 复杂任务,需要多次迭代才能正确完成
- 需要”don’t stop until it’s actually done”保证的场景
- 作为 Ultragoal 单个故事的执行引擎
何时不使用 Ralph:
- 简单的一次性任务(直接让 Codex 执行即可)
- 需要多目标拆解的项目(使用 Ultragoal)
参考来源
- Oh-My-Codex v0.18.9 源码 —
src/ralph/completion-audit.ts(完成审计评估) - Oh-My-Codex v0.18.9 源码 —
src/ralph/persistence.ts(PRD/进度迁移) - Oh-My-Codex v0.18.9 源码 —
src/ralph/contract.ts(相位/状态验证) - Oh-My-Codex v0.18.9 源码 —
skills/ralph/SKILL.md(工作流指令)