持久化多目标执行:Ultragoal 目标拆解与审计日志
持久化多目标执行:Ultragoal 目标拆解与审计日志
学习目标
- 理解 Ultragoal 如何通过三文件架构实现持久化多目标执行
- 掌握目标解析器、聚合目标模式与审计日志的具体实现
- 了解动态转向系统的六种变异类型和不变量约束
- 理解最终质量门控的三方独立验证与审查阻塞流
前置知识
本章涉及持久化目标执行的通用原理,建议先阅读:
下文假设你已理解上述概念,直接聚焦 Oh-My-Codex 的具体实现。
项目实践
三文件架构
Ultragoal 的核心状态存储在 .omx/ultragoal/ 目录:
.omx/ultragoal/├── brief.md # 原始简报(不可变)├── goals.json # 完整计划└── ledger.jsonl # 追加式审计日志目标解析器
Ultragoal 从用户的 markdown 简报中解析出离散目标:
伪代码(src/ultragoal/artifacts.ts — deriveGoalCandidates):function deriveGoalCandidates(briefMarkdown): candidates = [] goalId = 0
for item in parseTopLevelListItems(briefMarkdown): if not isNonGoalSection(item.parent): goalId++ candidates.push({ id: `G${String(goalId).padStart(3, "0")}`, title: extractTitle(item), objective: item.text, status: "pending", attempt: 0, createdAt: now(), updatedAt: now() })
return candidates非目标章节包括:“Acceptance criteria”、“Verification checklist”、“Background” 等。这些被识别为目标的辅助信息,不作为独立目标解析。
计划创建与原子写入
伪代码(src/ultragoal/artifacts.ts — createUltragoalPlan):function createUltragoalPlan(brief, codexGoalMode): candidates = deriveGoalCandidates(brief)
plan = { version: 1, createdAt: now(), updatedAt: now(), briefPath: ".omx/ultragoal/brief.md", goalsPath: ".omx/ultragoal/goals.json", ledgerPath: ".omx/ultragoal/ledger.jsonl", codexGoalMode: codexGoalMode, // "aggregate" | "per_story" codexObjective: buildAggregateObjective(candidates), goals: candidates }
// 原子写入三文件 withMutationLock(): write(".omx/ultragoal/brief.md", brief) writeAtomic(".omx/ultragoal/goals.json", plan) appendLedger({ ts: now(), event: "plan_created", message: `Plan with ${candidates.length} goals` })
return plan突变锁:使用 .omx/ultragoal/.mutation.lock 文件,通过 open("wx") 独占打开,重试退避最多 100 次。
Codex 目标模式
OMX 支持两种 Codex 目标集成模式:
聚合模式(aggregate,默认):
codexObjective = "Complete the durable ultragoal plan in .omx/ultragoal/goals.json, including later accepted/appended stories, under the original brief constraints; use .omx/ultragoal/ledger.jsonl as the audit trail."一个 Codex 目标代表整个 ultragoal 运行。本地 ledger 作为微目标追踪。
逐目标模式(per_story,旧版):
每个 OMX 故事(G001、G002…)映射 1:1 到一个 Codex 目标。
调度器:顺序执行与恢复
伪代码(src/ultragoal/artifacts.ts — startNextUltragoal):function startNextUltragoal(plan, options): // 聚合调和已完成 if plan.aggregateCompletion?.status == "complete": return { done: true }
// 恢复进行中的目标 inProgress = plan.goals.find(g => g.status == "in_progress" && isScheduleEligible(g)) if inProgress: inProgress.status = "in_progress" inProgress.startedAt = inProgress.startedAt || now() appendLedger({ event: "goal_resumed", goalId: inProgress.id }) return { goal: inProgress }
// 选择下一个 pending 目标 nextGoal = plan.goals.find(g => g.status == "pending" && isScheduleEligible(g)) if nextGoal: nextGoal.status = "in_progress" nextGoal.startedAt = now() appendLedger({ event: "goal_started", goalId: nextGoal.id }) return { goal: nextGoal }
// 可选:重试失败的目标 if options.retryFailed: failedGoal = plan.goals.find(g => g.status == "failed" && !g.nonRetriable) if failedGoal: failedGoal.status = "in_progress" failedGoal.attempt++ failedGoal.startedAt = now() appendLedger({ event: "goal_resumed", goalId: failedGoal.id, message: `Retry attempt ${failedGoal.attempt}` }) return { goal: failedGoal }
return { done: true }动态转向系统
OMX 的转向系统支持六种变异:
伪代码(转向验证器 — validateUltragoalSteeringProposal):function validateSteeringProposal(proposal): // 保护键不变量 PROTECTED_KEYS = ["aggregateCompletion", "brief", "codexObjective", "qualityGate", "status"] for key in PROTECTED_KEYS: if proposal.after[key] != undefined: return { valid: false, reason: `Cannot modify protected key: ${key}` }
// 禁止硬删除目标 if proposal.kind == "hard_delete": return { valid: false, reason: "Hard deletion is not allowed" }
// 禁止自动完成 if proposal.kind in ["auto_complete", "force_complete"]: return { valid: false, reason: "Auto-completion is not allowed" }
// 证据和理由检查 if not proposal.evidence or proposal.evidence.length == 0: return { valid: false, reason: "Steering requires evidence" }
// 幂等性 if existsIdempotencyKey(proposal.idempotencyKey): return { valid: false, reason: "Duplicate steering proposal" }
return { valid: true }转向变异类型的实现:
伪代码:function applySteeringMutation(plan, mutation): switch mutation.kind: case "add_subgoal": newGoal = { id: generateNextId(plan), ...mutation.goal, status: "pending" } plan.goals.push(newGoal) appendLedger({ event: "goal_added", goalId: newGoal.id })
case "split_subgoal": target = plan.goals.find(g => g.id == mutation.targetId) target.steeringStatus = "superseded" target.supersededBy = mutation.childIds for child in mutation.children: child.supersedes = [mutation.targetId] plan.goals.push(child)
case "reorder_pending": pending = plan.goals.filter(g => g.status == "pending") reordered = applyNewOrder(pending, mutation.newOrder) // 更新 plan.goals 中的 pending 目标顺序
case "mark_blocked_superseded": target = plan.goals.find(g => g.id == mutation.targetId) target.steeringStatus = mutation.newStatus // "blocked" | "superseded" if mutation.replacementIds: target.supersededBy = mutation.replacementIds最终质量门控
Ultragoal 的最终完成需要严格的质量门控:
伪代码(UltragoalQualityGate 结构):{ "aiSlopCleaner": { "status": "passed" }, "verification": { "status": "passed", "commands": ["npm run build", "npm test", "npm run lint"] }, "codeReview": { "recommendation": "APPROVE", "architectStatus": "CLEAR", "independentReview": [ { "agent": "code-reviewer", "evidence": "Reviewed 15 files, no critical issues" }, { "agent": "architect", "evidence": "Architecture consistent with PRD, all components accounted for" } ] }}质量门控验证:
伪代码:function validateQualityGate(qg): if qg.aiSlopCleaner.status != "passed": return { passed: false, reason: "AI slop cleaner not passed" } if qg.verification.status != "passed" or not qg.verification.commands?.length: return { passed: false, reason: "Verification not passed or no commands" } if qg.codeReview.recommendation != "APPROVE": return { passed: false, reason: "Code review not approved" } if qg.codeReview.architectStatus != "CLEAR": return { passed: false, reason: "Architect not cleared" }
// 检查独立审查证据 reviewers = qg.codeReview.independentReview if not reviewers?.find(r => r.agent == "code-reviewer"): return { passed: false, reason: "Missing code-reviewer evidence" } if not reviewers?.find(r => r.agent == "architect"): return { passed: false, reason: "Missing architect evidence" }
return { passed: true }审查阻塞流
当最终故事的代码审查非清洁时:
伪代码(recordFinalReviewBlockers):function recordFinalReviewBlockers(plan, currentGoalId, findings): currentGoal = plan.goals.find(g => g.id == currentGoalId) currentGoal.status = "review_blocked" currentGoal.reviewBlockedAt = now()
// 创建新的 blocker 解决故事 blockerId = generateNextId(plan) blockerGoal = { id: blockerId, title: `Resolve review blockers for ${currentGoalId}`, objective: `Fix: ${findings.join(", ")}`, status: "pending", supersededBy: [], supersedes: [currentGoalId] } plan.goals.push(blockerGoal)
appendLedger({ event: "goal_review_blocked", goalId: currentGoalId, message: `Blocked by review findings, created ${blockerId}` })
// 保持 Codex 目标活跃 return { newGoal: blockerGoal }任务作用域的聚合调和
特殊的逃生舱:如果外部完成的 Codex 目标与 ultragoal 简报内容重叠,可以跳过逐个目标的完成检查:
伪代码(task-scoped aggregate reconciliation):function evaluateTaskScopedReconciliation(completedGoal, plan): // 检查1: Codex 目标已完成 if completedGoal.status != "complete": return false
// 检查2: 目标内容与简报有内容重叠 contentOverlap = checkContentOverlap(completedGoal.objective, plan.brief) if contentOverlap < THRESHOLD: return false
// 检查3: 证据提到 .omx/ultragoal 工件 if not mentionsUltragoalArtifacts(completedGoal.evidence): return false
// 通过:设置聚合完成 plan.aggregateCompletion = { status: "complete", sourceGoalId: completedGoal.id, reason: "Task-scoped aggregate reconciliation" }
appendLedger({ event: "aggregate_completed", message: "Completed via task-scoped aggregate reconciliation" })
return trueCodex 目标快照协调
Ultragoal 与 Codex 目标工具的深度集成:
伪代码(src/goal-workflows/codex-goal-snapshot.ts — reconcileCodexGoalSnapshot):function reconcileCodexGoalSnapshot(snapshot, expectedObjective, allowedStatus): // 检查1: 快照可用 if not snapshot or snapshot.isDbError: return { reconciled: false, reason: "Snapshot not available" }
// 检查2: 目标匹配 if snapshot.objective != expectedObjective: aliases = getObjectiveAliases(expectedObjective) if not aliases.includes(snapshot.objective): return { reconciled: false, reason: "Objective mismatch" }
// 检查3: 状态匹配 if not allowedStatus.includes(snapshot.status): return { reconciled: false, reason: `Status ${snapshot.status} not in allowed: ${allowedStatus}` }
return { reconciled: true }问题与规避
| 问题 | 后果 | OMX 的规避策略 |
|---|---|---|
| JSONL 文件过大 | 读取审计日志时内存溢出 | 流式读取 + 分页,定期压缩归档 |
| 转向无限拆分目标 | 目标碎片化 | 设置最大拆分层级 |
| 文件锁持有者崩溃 | 后续操作永久阻塞 | PID 活跃度检查,超时自动释放 |
| 质量门控伪造 | 不合格代码被标记为完成 | 独立验证:三方证据必须可验证 |
| 审查阻塞无限循环 | 反复 blocker 解决又阻塞 | 设置最大 blocker 解决次数 |
设计取舍
为什么选择文件存储而非数据库?
OMX 选择 JSON + JSONL 文件存储目标状态,而非数据库。
优势:
- 零依赖:不需要数据库服务器
- 可读性:直接
cat查看,无需 SQL 查询 - 便携性:
.omx/目录随项目一起迁移 - JSONL 天然追加式审计:每行一个事件
代价:
- 并发控制较弱:文件锁 vs 数据库事务
- 查询能力有限:无法高效过滤/排序
- 单 Agent 场景适用:多 Agent 并发操作需要额外同步
替代方案:
- SQLite 嵌入:更轻量,支持 SQL 查询和事务
- 数据库(PostgreSQL/Drizzle):适合多 Agent 场景,但增加部署复杂度
参考来源
- Oh-My-Codex v0.18.9 源码 —
src/ultragoal/artifacts.ts(1613 行,主要实现) - Oh-My-Codex v0.18.9 源码 —
src/goal-workflows/codex-goal-snapshot.ts(目标快照协调) - Oh-My-Codex v0.18.9 源码 —
src/verification/(质量门控验证) - Oh-My-Codex v0.18.9 源码 —
skills/ultragoal/SKILL.md(工作流指令)