/**
 * Convergence Loop
 *
 * Drives an underlying model through execute → apply → verify → feedback
 * iterations until the project's completion gates (verifier ladder) pass or
 * the turn budget is exhausted.
 *
 * The loop owns pluggable seams so phases extend without breaking changes:
 *  - executor: how a prompt becomes model output
 *  - applier: how model output is materialized into the project tree
 *  - promptBuilder: how instruction/feedback/critique compose a prompt
 *  - ladderRunner: how gates are verified
 *  - explorer (Phase 2): best-of-N candidate exploration with judge tie-break
 *  - critic (Phase 3): structured repair plans replacing raw gate dumps
 *  - onIteration: per-turn control hook (Phase 5 escalation controllers)
 */
import type { GateRung, LadderResult, LadderOptions } from './verifier-ladder.js';
import type { Applier } from './applier.js';
import type { StrategySeed } from './explorer.js';
import type { Judge } from './judge.js';
import type { Critic } from './critic.js';
export type LoopExecutor = (prompt: string) => Promise<string>;
/** Pluggable ladder runner — production uses runLadder, tests inject a stub. */
export type LadderRunner = (rungs: GateRung[], projectRoot: string, options?: LadderOptions) => LadderResult | Promise<LadderResult>;
export interface PromptContext {
    instruction: string;
    /** 1-based turn about to execute */
    turn: number;
    /** Model output from the previous turn (truncated) */
    previousOutput?: string;
    /** Gate feedback from the previous turn's ladder run */
    feedback?: string;
    /** Apply-stage error from the previous turn (e.g. no file blocks found) */
    applyError?: string;
    /** Files written by the previous turn */
    previousFiles?: string[];
    /** Structured repair steps from the critic (Phase 3) */
    critique?: string[];
    /** Best-practice guidance retrieved for this task (Phase 4) */
    practices?: string[];
}
export type PromptBuilder = (context: PromptContext) => string;
export interface CandidateSummary {
    id: string;
    strategy: string;
    passed: boolean;
    score: number;
    error?: string;
}
export interface IterationRecord {
    /** Real 1-based loop turn (executor-error turns are recorded too) */
    turn: number;
    passed: boolean;
    /** Fraction of gates passed this iteration (0 when the turn never reached verification) */
    score: number;
    gateResults: LadderResult['results'];
    /** Files the applier wrote this turn */
    filesApplied: string[];
    /** Executor failure, if the model call itself errored */
    executorError?: string;
    /** Apply failure, if output could not be materialized */
    applyError?: string;
    /** Strategy seed of the committed candidate (explorer mode) */
    strategy?: string;
    /** All candidates evaluated this turn (explorer mode) */
    candidates?: CandidateSummary[];
    /** Judge rationale when a tie-break decided the winner (explorer mode) */
    judgeRationale?: string;
    durationMs: number;
}
export interface DeliveryResult {
    success: boolean;
    /** True when the baseline check found all gates already green (no turns ran) */
    alreadyDelivered: boolean;
    turns: number;
    /** Highest gate score observed across iterations */
    bestScore: number;
    /** Turn that achieved bestScore (0 when no iterations reached verification) */
    bestTurn: number;
    history: IterationRecord[];
    /** Feedback from the final ladder run (or apply/executor error context) */
    finalFeedback: string;
    /** Raw model output from the final turn */
    finalOutput: string;
    totalDurationMs: number;
}
export interface ExplorerSettings {
    /** Candidates per turn (default 3) */
    candidates?: number;
    seeds?: StrategySeed[];
    judge?: Judge;
}
/**
 * Directive returned from onIteration to steer the loop (Phase 5).
 * All fields are optional; an empty object (or void) means "continue".
 * 'stop' (string) remains supported for backward compatibility.
 */
export interface IterationDirective {
    /** Abort the loop after this turn */
    stop?: boolean;
    /** Raise the turn budget to this absolute value (ignored if ≤ current) */
    raiseMaxTurns?: number;
    /** Enable/resize best-of-N exploration starting next turn */
    setCandidates?: number;
    /** Turn the structured critic on starting next turn */
    enableCritic?: boolean;
    /** Swap the model/executor (model escalation) */
    switchExecutor?: LoopExecutor;
    /** Human-readable reason, surfaced in logs and the iteration record */
    note?: string;
}
export type OnIteration = (record: IterationRecord) => void | 'stop' | IterationDirective;
/** Retrieve best-practice guidance for a task (Phase 4). */
export type PracticeProvider = (instruction: string) => string[] | Promise<string[]>;
export interface ConvergenceConfig {
    /** Maximum execute→apply→verify iterations (default 5) */
    maxTurns?: number;
    /** Project whose gates define "delivered" */
    projectRoot: string;
    /** Override auto-detected gates (e.g. subset via CLI --gates) */
    rungs?: GateRung[];
    /** Ladder options forwarded to the runner */
    ladderOptions?: LadderOptions;
    /**
     * Run the ladder once before turn 1 (default true). When the baseline is
     * already green there is nothing to converge on — the loop returns
     * alreadyDelivered without calling the model, preventing false-success
     * outcomes from polluting adaptive routing.
     */
    baselineCheck?: boolean;
    /** Max characters of prior model output included in retry prompts (default 3000) */
    previousOutputChars?: number;
    /** Best-of-N exploration per turn (Phase 2); omit for single-candidate turns */
    explorer?: ExplorerSettings;
    /** Structured critique of failed turns (Phase 3) */
    critic?: Critic;
    /** Best-practice guidance injected into prompts (Phase 4) */
    practiceProvider?: PracticeProvider;
    /** Factory the escalation controller uses to build a critic when it
     * enables one mid-run (Phase 5). Receives the current executor so the
     * critic uses the same (possibly escalated) model as generation. */
    criticFactory?: (executor: LoopExecutor) => Critic;
    /**
     * Called after every iteration. Return 'stop' or an IterationDirective to
     * steer the loop (Phase 5 escalation controllers hook in here).
     */
    onIteration?: OnIteration;
}
/** Default prompt strategy: lean contract + structured retry context. */
export declare const defaultPromptBuilder: PromptBuilder;
export declare class ConvergenceLoop {
    private readonly config;
    private readonly executor;
    private readonly ladderRunner;
    private readonly applier;
    private readonly promptBuilder;
    constructor(config: ConvergenceConfig, executor: LoopExecutor, seams?: {
        ladderRunner?: LadderRunner;
        applier?: Applier;
        promptBuilder?: PromptBuilder;
    });
    /** Single-candidate turn: execute → apply → verify. */
    private runSingleTurn;
    /** Explorer turn: best-of-N candidates, commit the winner (Phase 2). */
    private runExplorerTurn;
    /**
     * Run the loop for an instruction until all required gates pass or the
     * turn budget is exhausted. Returns the full iteration history so callers
     * can record outcomes and inspect convergence behavior.
     */
    deliver(instruction: string): Promise<DeliveryResult>;
}
//# sourceMappingURL=convergence-loop.d.ts.map