Files
oh-my-opencode/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts
T
YeonGyu-Kim 8c6e8e4986 refactor(omo-codex): rename ultragoal component to ulw-loop
Fully rename the ultragoal component to ulw-loop so the identifier
matches the ulw-loop skill it powers. Renames the component directory,
nested skill, TS identifiers (UlwLoop / ULW_LOOP_* / ulwLoop*), the
omo ulw-loop CLI subcommand, the .omo/ulw-loop state directory, the
OMO_ULW_LOOP_STEER directive token, and the @code-yeongyu/codex-ulw-loop
package. Also threads Atlas-style right-sized parallel worker delegation
and a Prometheus-style QA + maximum-parallelism plan into the ulw-loop
skill, with a critical post-subagent QA gate.

Updates aggregate wiring (plugin package components, hooks.json,
sync-skills), the install-codex agent-link test fixture, and user docs.
2026-05-29 12:38:22 +09:00

85 lines
3.1 KiB
TypeScript

import type {
UlwLoopCodexGoalMode,
UlwLoopItem,
UlwLoopPlan,
UlwLoopStatus,
UlwLoopSuccessCriterion,
} from "./types.js";
export const ULW_LOOP_AGGREGATE_CODEX_OBJECTIVE: string =
"Complete the durable ulw-loop plan in .omo/ulw-loop/goals.json, including later accepted/appended stories, under the original brief constraints; use .omo/ulw-loop/ledger.jsonl as the audit trail.";
export function codexGoalMode(plan: UlwLoopPlan): UlwLoopCodexGoalMode {
return plan.codexGoalMode ?? "per_story";
}
function isResolvedStatus(status: UlwLoopStatus): boolean {
return status === "complete";
}
function isSupersededResolved(goal: UlwLoopItem, plan: UlwLoopPlan): boolean {
if (goal.steeringStatus !== "superseded") return false;
const replacements = goal.supersededBy ?? [];
if (replacements.length === 0) return false;
return replacements.every((id) => {
const replacement = plan.goals.find((candidate) => candidate.id === id);
return replacement !== undefined && isResolvedStatus(replacement.status);
});
}
function isCompletionBlocking(goal: UlwLoopItem, plan: UlwLoopPlan): boolean {
if (goal.steeringStatus === "superseded") return !isSupersededResolved(goal, plan);
if (goal.steeringStatus === "blocked") return true;
return !isResolvedStatus(goal.status);
}
function isCompletionBlockingForFinalCandidate(
candidate: UlwLoopItem,
finalCandidate: UlwLoopItem,
plan: UlwLoopPlan,
): boolean {
if (candidate.id === finalCandidate.id) return false;
if (candidate.steeringStatus === "superseded") {
const replacements = candidate.supersededBy ?? [];
if (replacements.length === 0) return true;
return !replacements.every((id) => {
if (id === finalCandidate.id) return true;
const replacement = plan.goals.find((goal) => goal.id === id);
return replacement !== undefined && isResolvedStatus(replacement.status);
});
}
return isCompletionBlocking(candidate, plan);
}
export function isUlwLoopDone(plan: UlwLoopPlan): boolean {
if (plan.aggregateCompletion?.status === "complete") return true;
return plan.goals.every((goal) => !isCompletionBlocking(goal, plan));
}
export function isFinalRunCompletionCandidate(plan: UlwLoopPlan, goal: UlwLoopItem): boolean {
return (
isCompletionBlocking(goal, plan) &&
plan.goals.every((candidate) => !isCompletionBlockingForFinalCandidate(candidate, goal, plan))
);
}
export function aggregateCodexObjective(plan: UlwLoopPlan): string {
return plan.codexObjective ?? ULW_LOOP_AGGREGATE_CODEX_OBJECTIVE;
}
export function expectedCodexObjective(plan: UlwLoopPlan, goal: UlwLoopItem): string {
return codexGoalMode(plan) === "aggregate" ? aggregateCodexObjective(plan) : goal.objective;
}
export function compatibleCodexObjectives(plan: UlwLoopPlan): readonly string[] {
return [aggregateCodexObjective(plan), ...(plan.codexObjectiveAliases ?? [])];
}
export function hasAllCriteriaPass(goal: UlwLoopItem): boolean {
return goal.successCriteria.length > 0 && goal.successCriteria.every((criterion) => criterion.status === "pass");
}
export function firstUnresolvedCriterion(goal: UlwLoopItem): UlwLoopSuccessCriterion | undefined {
return goal.successCriteria.find((criterion) => criterion.status !== "pass");
}