跳转到内容

持久完成循环:Ralph 单任务迭代与完成审计

持久完成循环:Ralph 单任务迭代与完成审计

学习目标

  • 理解 Ralph 循环的迭代步骤和状态流转
  • 掌握完成审计的三层检查(存在性 → 通过判定 → 检查清单与证据)
  • 了解视觉门控和 Deslop 清理的具体实现
  • 理解 Ralph 与 Ultragoal 的组成关系

前置知识

本章涉及持久完成循环的通用原理,建议先阅读:

下文假设你已理解上述概念,直接聚焦 Oh-My-Codex 的具体实现。


项目实践

Ralph 循环的迭代步骤

Ralph 的 SKILL.md 定义了编号的步骤序列:

Step 0: 上下文快照 → .omx/context/{task-slug}-{timestamp}.md
Step 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) + /cancel
Step 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_checklistpromptToArtifactChecklistchecklist),以兼容不同版本的产出格式。

视觉门控

对于视觉相关任务(如 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.jsonvisual_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(工作流指令)