71e4e2a6d0
Goal content under ./.omo/ultragoal/sessions/claude-<id>/ keyed by Claude Code session_id (claude: prefix); UltragoalScope struct threaded; plan version 2 + index.json registry with read-only v1 forward-migration (never deletes v1); create_goal/get_goal/update_goal dependency dropped (file/steering-based); the PreToolUse create_goal budget guard kept compiled+unit-tested but its hooks.json registration removed (inert in CC). 26 tests pass. ultragoal removed from sync-components HANDLED set — it is a hand-fork, not patch-synced. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
3.1 KiB
TypeScript
85 lines
3.1 KiB
TypeScript
import type {
|
|
UltragoalGoalMode,
|
|
UltragoalItem,
|
|
UltragoalPlan,
|
|
UltragoalStatus,
|
|
UltragoalSuccessCriterion,
|
|
} from "./types.js";
|
|
|
|
export const ULTRAGOAL_AGGREGATE_OBJECTIVE: string =
|
|
"Complete the durable ultragoal plan in .omo/ultragoal/goals.json, including later accepted/appended stories, under the original brief constraints; use .omo/ultragoal/ledger.jsonl as the audit trail.";
|
|
|
|
export function goalMode(plan: UltragoalPlan): UltragoalGoalMode {
|
|
return plan.goalMode ?? "per_story";
|
|
}
|
|
|
|
function isResolvedStatus(status: UltragoalStatus): boolean {
|
|
return status === "complete";
|
|
}
|
|
|
|
function isSupersededResolved(goal: UltragoalItem, plan: UltragoalPlan): 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: UltragoalItem, plan: UltragoalPlan): boolean {
|
|
if (goal.steeringStatus === "superseded") return !isSupersededResolved(goal, plan);
|
|
if (goal.steeringStatus === "blocked") return true;
|
|
return !isResolvedStatus(goal.status);
|
|
}
|
|
|
|
function isCompletionBlockingForFinalCandidate(
|
|
candidate: UltragoalItem,
|
|
finalCandidate: UltragoalItem,
|
|
plan: UltragoalPlan,
|
|
): 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 isUltragoalDone(plan: UltragoalPlan): boolean {
|
|
if (plan.aggregateCompletion?.status === "complete") return true;
|
|
return plan.goals.every((goal) => !isCompletionBlocking(goal, plan));
|
|
}
|
|
|
|
export function isFinalRunCompletionCandidate(plan: UltragoalPlan, goal: UltragoalItem): boolean {
|
|
return (
|
|
isCompletionBlocking(goal, plan) &&
|
|
plan.goals.every((candidate) => !isCompletionBlockingForFinalCandidate(candidate, goal, plan))
|
|
);
|
|
}
|
|
|
|
export function aggregateObjective(plan: UltragoalPlan): string {
|
|
return plan.objective ?? ULTRAGOAL_AGGREGATE_OBJECTIVE;
|
|
}
|
|
|
|
export function expectedObjective(plan: UltragoalPlan, goal: UltragoalItem): string {
|
|
return goalMode(plan) === "aggregate" ? aggregateObjective(plan) : goal.objective;
|
|
}
|
|
|
|
export function compatibleObjectives(plan: UltragoalPlan): readonly string[] {
|
|
return [aggregateObjective(plan), ...(plan.objectiveAliases ?? [])];
|
|
}
|
|
|
|
export function hasAllCriteriaPass(goal: UltragoalItem): boolean {
|
|
return goal.successCriteria.length > 0 && goal.successCriteria.every((criterion) => criterion.status === "pass");
|
|
}
|
|
|
|
export function firstUnresolvedCriterion(goal: UltragoalItem): UltragoalSuccessCriterion | undefined {
|
|
return goal.successCriteria.find((criterion) => criterion.status !== "pass");
|
|
}
|