import { type UlwLoopScope, ulwLoopAttemptEvidenceDir } from "./paths.js"; import { readUlwLoopPlan } from "./plan-io.js"; import { resolveToolkitSurface, type UlwLoopToolkitSurface } from "./surface.js"; import type { UlwLoopPlan } from "./types.js"; import { UlwLoopError } from "./types.js"; export interface CheckpointTemplate { readonly qualityGateTemplate: Record; readonly codexGoalTemplate: Record; readonly attemptDir?: string; readonly guidance?: string; } export interface CheckpointTemplateDependencies { readonly surface?: UlwLoopToolkitSurface; } function artifactPath(base: string, name: string): string { return `${base}/${name}`; } function gateTemplate(surface: UlwLoopToolkitSurface, base: string): Record { const artifacts = [ { id: "artifact-cli", kind: "cli-transcript", description: "", path: artifactPath(base, "cli-transcript.txt"), }, { id: "artifact-data", kind: "data-diff", description: "", path: artifactPath(base, "data-diff.txt"), }, ]; const manualQa = { by: "main-session", status: "passed", evidence: "", surfaceEvidence: [ { id: "surface-cli", criterionRef: "", surface: "cli", invocation: "", verdict: "passed", artifactRefs: ["artifact-cli"], }, { id: "surface-data", criterionRef: "", surface: "data", invocation: "", verdict: "passed", artifactRefs: ["artifact-data"], }, ], adversarialCases: [ { id: "", criterionRef: "", scenario: "", expectedBehavior: "", verdict: "not_applicable", reason: "", artifactRefs: ["artifact-cli"], }, ], artifactRefs: artifacts, }; const common = { manualQa, gateReview: { by: surface === "omo-senpi" ? "category:deep-high" : "main-session", recommendation: "APPROVE", reportPath: artifactPath(base, "gate-review.md"), evidence: "", blockers: [], notes: [], }, iteration: { fullRerun: true, status: "passed", rerunCommands: [""], evidence: "", }, criteriaCoverage: { totalCriteria: 0, passCount: 0, originalIntent: "", desiredOutcome: "", userOutcomeReview: "", adversarialClassesCovered: [""], }, }; return common; } export async function checkpointTemplate( repoRoot: string, scope?: UlwLoopScope, goalId?: string, dependencies?: CheckpointTemplateDependencies, ): Promise { const plan: UlwLoopPlan = await readUlwLoopPlan(repoRoot, scope); const surface = dependencies?.surface ?? resolveToolkitSurface(); const targetId = goalId ?? plan.activeGoalId; const active = plan.goals.find((goal) => goal.id === targetId); if (goalId !== undefined && active === undefined) throw new UlwLoopError(`Unknown ulw-loop id: ${goalId}.`, "ULW_LOOP_GOAL_NOT_FOUND", { details: { goalId } }); const hasAttempt = plan.evidenceLayoutVersion === 2 && active !== undefined; const attemptDir = hasAttempt ? ulwLoopAttemptEvidenceDir(active.id, active.attempt, scope) : ".omo/evidence"; const guidance = [ "codex-goal-json requires goal.objective to equal the plan's codexObjective verbatim; do not paraphrase it.", "Fill every value with plausible non-empty evidence and use real, non-empty artifact files.", 'Passing codex-goal-json example: {"goal":{"objective":"","status":"complete"}}.', 'Passing quality-gate-json example requires gateReview {"by":"category:deep-high","recommendation":"APPROVE","evidence":"review passed","reportPath":"/gate-review.md","blockers":[],"notes":[]}, manualQa.artifactRefs objects, iteration, and criteriaCoverage.', ...(surface === "lazycodex" ? [ "Self-review defaults: manualQa.by and gateReview.by are main-session. Alternatives: manualQa.by accepts lazycodex-qa-executor; gateReview.by accepts lazycodex-gate-reviewer, category:deep-high, category:deep-low, category:unspecified-high, or category:unspecified-low. Optional codeReview.by accepts lazycodex-code-reviewer or main-session.", ] : []), ...(hasAttempt ? [] : ["This plan is evidence-layout v1; artifacts go under .omo/evidence/."]), ].join(" "); return { qualityGateTemplate: gateTemplate(surface, attemptDir), codexGoalTemplate: { goal: { objective: plan.codexObjective ?? "", status: "complete" }, }, guidance, ...(hasAttempt ? { attemptDir } : {}), }; }