/** * Turn-budgeted goal loop (Layer 4 of SG-COGNITIVE-SUBSTRATE). * * The loop is the Hermes-style post-turn driver, hardened: it consumes one turn * per advance, enforces a hard {@link GoalRecord.turnBudget}, surfaces * `impossible` verdicts as a terminal state (no further turns), and — the Hermes * pattern that prevents silent crashes — AUTO-PAUSES on a judge/parse failure * rather than aborting. * * `advanceGoal` is PURE and DETERMINISTIC over `(goal, judgeFn)`: it performs no * I/O itself (the judge is injected; persistence is the caller's job via the * store's `updateGoal`). This makes every transition trivially unit-testable * offline and keeps the budget/impossible/pause logic in one auditable place. * * Transition table (the four AC-mandated outcomes): * - `verdict.ok` → `satisfied` (terminal). * - `verdict.impossible` → `impossible` (terminal; consumes NO turn). * - judge/parse failure → `paused` (auto-pause, `pausedReason` set). * - turn budget reached → `abandoned` (terminal). * - otherwise → `active` (one turn consumed; keep going). * * @module @cleocode/core/goal/loop * * @epic T11290 EP-CLEO-GOAL-SYSTEM * @task T11379 * @saga T11283 SG-COGNITIVE-SUBSTRATE */ import type { GoalAdvanceResult, GoalJudgeVerdict, GoalRecord } from '@cleocode/contracts'; /** * A judge function the loop invokes once per advance. Injected so the loop is * pure over `(goal, judgeFn)` — production passes a closure over `judgeGoal`, * tests pass a deterministic stub. * * @param goal - The goal being advanced. * @returns The verdict for this turn. * @task T11379 */ export type GoalJudgeFn = (goal: GoalRecord) => Promise; /** * A minimal, well-formed {@link GoalJudgeVerdict}-shaped object check. * * A judge that returns a malformed value (missing `ok`/`impossible`, wrong * types) is treated as a PARSE FAILURE — the goal auto-pauses rather than * trusting a garbage verdict. This is the structural half of the Hermes * parse-failure pattern (the thrown-error half is handled by the try/catch in * {@link advanceGoal}). * * @param value - The judge's return value. * @returns `true` when `value` is a structurally-valid verdict. * @task T11379 */ export declare function isWellFormedVerdict(value: unknown): value is GoalJudgeVerdict; /** * Advance a goal one turn through the budgeted loop. * * Pure and deterministic over `(goal, judgeFn)` — NO persistence here; the * caller persists the returned `nextStatus` / `turnsRemaining` via the goal * store's `updateGoal`. Already-terminal goals are returned unchanged (no turn * is consumed, no judge is called) so the loop is idempotent at its boundaries. * * Ordering rationale: * - The judge runs FIRST so a goal that became satisfiable/impossible since the * last turn is detected before a turn is "spent". * - `impossible` consumes NO turn (the verdict is final regardless of budget). * - `ok` consumes NO turn (work is done). * - Only the "keep going" path consumes a turn, and the budget check fires AFTER * incrementing so `turnsRemaining` never goes negative. * * @param goal - The current goal record. * @param judgeFn - The injected judge (see {@link GoalJudgeFn}). * @returns The verdict, the next status, and the remaining turns. * @task T11379 */ export declare function advanceGoal(goal: GoalRecord, judgeFn: GoalJudgeFn): Promise; //# sourceMappingURL=loop.d.ts.map