/**
 * # `selfImprove()` - the one-call improvement loop.
 *
 * The cheapest possible call site to run a real closed-loop self-
 * improvement over your agent. Wraps `runImprovementLoop` with smart
 * defaults and a budget-shaped options API; every escape hatch the
 * substrate exposes is reachable from here without losing the
 * one-function feel.
 *
 * Defaults:
 *   - In-memory storage (no filesystem touch).
 *   - `gepaProposer` reflective mutation with copywriting-flavored primitives
 *     (override `proposer` or `mutationPrimitives` for any domain).
 *   - `defaultProductionGate` with `deltaThreshold: 0.05`.
 *   - Held-out split = 25% of scenarios, deterministic by id hash.
 *   - 3 generations × population 2 (raise via `budget` for more search).
 *   - `autoOnPromote: 'none'` (we don't open PRs unless you ask).
 *
 * Want one-click? Provide `agent` + `scenarios` + `judge`. Done.
 * Want distributed? Pass `cellPlacement` + an `httpDispatch`-backed
 * agent. Want a code-tier surface? Pass a `MutableSurface` + your own
 * `proposer`. Same function.
 */
import { type RunImprovementLoopResult } from '../campaign/presets/run-improvement-loop';
import type { RunOptimizationOptions } from '../campaign/presets/run-optimization';
import { type LoopProvenanceRecord } from '../campaign/provenance';
import { type CampaignStorage } from '../campaign/storage';
import type { DispatchContext, Gate, JudgeConfig, LabeledScenarioStore, MutableSurface, Scenario, SurfaceProposer } from '../campaign/types';
import { type HostedTenant } from '../hosted/client';
import type { RunRecord } from '../run-record';
import type { InsightReport } from './insight-report';
export interface SelfImproveBudget {
    /** Hard $ ceiling across all cells in baseline + every generation. Cells
     *  beyond the ceiling are skipped (cost-aware, not aborted). */
    dollars?: number;
    /** How many improvement generations to explore. Default 3. Set 0 to
     *  skip improvement entirely (selfImprove becomes a baseline-only run). */
    generations?: number;
    /** Candidates the proposer emits per generation. Default 2. */
    populationSize?: number;
    /** Max concurrent cells across the loop. Default 2. */
    maxConcurrency?: number;
    /** Fraction of `scenarios` held out from training, used for the gate.
     *  Default 0.25. Ignored when `holdoutScenarios` is set explicitly. */
    holdoutFraction?: number;
    /** Explicit held-out scenarios; overrides `holdoutFraction`. */
    holdoutScenarios?: Scenario[];
    /** Per-scenario replicates per cell — raises bootstrap-CI tightness. Default 1. */
    reps?: number;
    /** Top-scoring candidates carried into the next generation. Default 2. */
    promoteTopK?: number;
}
export interface SelfImproveLlm {
    /** Endpoint base URL. Default Tangle Router. */
    baseUrl?: string;
    /** Bearer token. Default `process.env.OPENAI_API_KEY`. */
    apiKey?: string;
    /** Model id used by `gepaProposer` reflection. Default
     *  `anthropic/claude-sonnet-4.6`. */
    model?: string;
}
export type SelfImproveProgressEvent = {
    kind: 'baseline.started';
    scenarios: number;
} | {
    kind: 'baseline.completed';
    compositeMean: number;
    durationMs: number;
} | {
    kind: 'generation.started';
    index: number;
    populationSize: number;
} | {
    kind: 'generation.completed';
    index: number;
    bestComposite: number;
    durationMs: number;
} | {
    kind: 'gate.decided';
    decision: string;
    lift: number;
};
export interface SelfImproveOptions<TScenario extends Scenario, TArtifact> {
    /**
     * Your agent — a function that takes the current `MutableSurface`
     * (typically a system prompt the loop is optimizing) plus the
     * scenario + cell ctx, and returns the artifact your judge scores.
     *
     * Same shape as `RunOptimizationOptions.dispatchWithSurface`. Wrap a
     * plain `Dispatch` if you don't have a surface seam:
     *
     *   agent: (_surface, scenario, ctx) => yourPlainDispatch(scenario, ctx)
     *
     * That mode evaluates without mutating any surface — useful as a
     * baseline-only run (set `budget.generations = 0`).
     */
    agent: (surface: MutableSurface, scenario: TScenario, ctx: DispatchContext) => Promise<TArtifact>;
    /** Scenarios to evaluate against. Train/holdout split is computed from
     *  these unless `budget.holdoutScenarios` is set explicitly. */
    scenarios: TScenario[];
    /** Judge that scores artifacts. Bring your own; use `langchainJudge`
     *  from `/adapters/langchain` for a Runnable-shaped one. */
    judge: JudgeConfig<TArtifact, TScenario>;
    /** Starting surface — system prompt, JSON config, anything `MutableSurface`
     *  accepts. The proposer mutates this each generation. */
    baselineSurface: MutableSurface;
    /** Budget + loop shape. All fields optional. */
    budget?: SelfImproveBudget;
    /** Custom surface proposer. Default is `gepaProposer` configured from `llm` +
     *  `mutationPrimitives`. */
    proposer?: SurfaceProposer;
    /** Default-proposer overrides — used when `proposer` is unset. */
    mutationPrimitives?: string[];
    proposerTarget?: string;
    /** Custom gate. Default is `defaultProductionGate` with
     *  `deltaThreshold: 0.05` on the held-out split. */
    gate?: Gate<TArtifact, TScenario>;
    /** LLM config consumed by the default `gepaProposer`. Ignored if you pass
     *  your own `proposer`. */
    llm?: SelfImproveLlm;
    /** Storage backend. Default is DURABLE: when a real (non-`mem://`) `runDir`
     *  is available, the substrate defaults to `fsCampaignStorage()` so the
     *  provenance record + OTel spans survive the call. Pass
     *  `inMemoryCampaignStorage()` explicitly to opt OUT (tests, edge runtimes).
     *  Default when `runDir` is `mem://...` (or unset): in-memory. */
    storage?: CampaignStorage;
    /** Run directory (logical for in-memory storage, real path for fs).
     *  Default `mem://selfImprove-<timestamp>` (in-memory, non-durable). Pass a
     *  real path to persist the provenance record + spans. */
    runDir?: string;
    /**
     * Worker call records for backend provenance. The agent is opaque to the
     * substrate (it returns an artifact, not token usage), so to capture an
     * `assertRealBackend`-grade verdict + worker call count + model in the
     * provenance record, the agent reports its per-call `RunRecord`s here.
     * Called once after the loop; return the records the agent accumulated.
     * When unset, backend provenance is derived from campaign cells (cost only;
     * verdict will read `stub` without token usage — the honest signal that no
     * token channel was wired).
     */
    collectWorkerRecords?: () => RunRecord[];
    /** Fires once the durable provenance record + OTel spans are emitted.
     *  Receives the structured record for inline assertions / custom routing. */
    onProvenance?: (record: LoopProvenanceRecord) => void;
    /** Distributed execution seam — same as `RunCampaignOptions.cellPlacement`.
     *  Returns an opaque placement key the substrate forwards to your agent
     *  as `ctx.placement`. Combined with `httpDispatch` from
     *  `/adapters/http`, fans cells across regions. */
    cellPlacement?: (input: {
        scenario: TScenario;
        rep: number;
        generation?: number;
    }) => string | undefined;
    /** Streaming hook — fires on baseline + each generation + gate decision.
     *  Consumer routes events wherever (UI, dashboard, logs). */
    onProgress?: (event: SelfImproveProgressEvent) => void;
    /** Auto-promotion behavior on a ship decision. Default `'none'` — we
     *  return the winner; you ship it however you ship. `'pr'` opens a
     *  GitHub PR via `openAutoPr`; requires `ghOwner` + `ghRepo`. */
    autoOnPromote?: 'pr' | 'none';
    ghOwner?: string;
    ghRepo?: string;
    /**
     * Opt-in: ship eval-run events to a hosted orchestrator (ours, your
     * self-hosted one, or any compatible implementation of the
     * `docs/hosted-ingest-spec.md` wire format). When set, the substrate
     * POSTs the final `EvalRunEvent` to `${endpoint}/v1/ingest/eval-runs`
     * after the loop completes. Failures are logged but do not fail the
     * loop — local result is always returned.
     *
     * For our orchestrator: `{ endpoint: 'https://orchestrator.tangle.tools/v1', apiKey, tenantId }`.
     *
     * For your self-hosted: any URL serving the wire format. See
     * `examples/hosted-ingest-server/` for the reference receiver.
     */
    hostedTenant?: HostedTenant;
    /** Free-form labels attached to the hosted event (env, branch, model id,
     *  etc.). Ignored when `hostedTenant` is unset. */
    hostedLabels?: Record<string, string>;
    /** Capture every artifact + judge score to this store (labeled-example
     *  corpus the proposer may read for few-shot, and the dataset you ship). Pass
     *  `'off'` to disable. Default: off. */
    labeledStore?: LabeledScenarioStore | 'off';
    /** Capture-source tag for `labeledStore`. Default `'eval-run'`. */
    captureSource?: 'production-trace' | 'eval-run' | 'manual' | 'red-team' | 'synthetic';
    /**
     * Per-cell backend-integrity expectation — the fail-loud guard. A cell that
     * produced an artifact but reported `costUsd === 0` AND zero tokens is a
     * stub. Modes: `'assert'` throws on the first such cell, `'warn'` logs it,
     * `'off'` skips the check (offline/replay). Default `'assert'` — `selfImprove`
     * is the real-run path, so a stub fails loud rather than scoring a clean 0.
     */
    expectUsage?: 'assert' | 'warn' | 'off';
    /**
     * Per-generation findings producer. After each
     * generation is scored, this is called; whatever it returns REPLACES the
     * proposer's `findings` for the next generation's `propose()`. Plug a
     * trace-analyst registry / HALO here. When absent, findings stay
     * `opts.findings`.
     */
    analyzeGeneration?: RunOptimizationOptions<TScenario, TArtifact>['analyzeGeneration'];
    /** Static findings forwarded to the proposer's `propose()` as `ctx.findings`
     *  (a findings-grounded proposer consumes them). Default: none. */
    findings?: unknown[];
}
export interface SelfImproveResult<TScenario extends Scenario, TArtifact> {
    /** Composite mean across all scenarios, baseline run. */
    baseline: {
        compositeMean: number;
        perScenario: Record<string, number>;
    };
    /** Composite mean on the held-out set, winner run. */
    winner: {
        compositeMean: number;
        perScenario: Record<string, number>;
        surface: MutableSurface;
        /** Proposer label for the promoted change. Absent ⇒ winner == baseline or
         *  a bare-surface mutator. */
        label?: string;
        /** Proposer rationale — the "because Z" that motivated the promoted change.
         *  Threaded from the proposer's `ProposedCandidate` through the loop.
         *  Absent ⇒ winner == baseline. */
        rationale?: string;
    };
    /** `winner.compositeMean - baselineOnHoldout.compositeMean`. Positive
     *  means the gate observed improvement. */
    lift: number;
    /** The explicit baseline→winner unified diff. Always present (empty string
     *  when winner == baseline). */
    diff: string;
    /** Durable, queryable provenance record: candidate→cell→gate→promote chain +
     *  rationale + diff + backend provenance. The artifact the hosted ingest
     *  path stores; the +lift RECOMPUTES from `record.heldOutLift`. */
    provenance: LoopProvenanceRecord;
    /** `defaultProductionGate.decide()` result. */
    gateDecision: 'ship' | 'hold' | 'need_more_work' | 'model_ceiling' | 'arch_ceiling';
    /** Number of generations actually explored (may be less than the
     *  budget if the proposer gave up early). */
    generationsExplored: number;
    /** Wall-clock total. */
    durationMs: number;
    /** Total cost across baseline + every generation. */
    totalCostUsd: number;
    /**
     * Rigor packet: distributional summary, paired-bootstrap lift CI,
     * judge stats, contamination check, recommendations. Wired through
     * `analyzeRuns()` on the baseline + winner cells of the campaign.
     * Hosted-tier dashboards render this as the v3-vs-v4 decision view.
     */
    insight: InsightReport;
    /**
     * Raw substrate result for advanced inspection — full per-generation
     * candidates, full campaign artifacts, all judge scores. Useful for
     * debugging or reporting beyond the summary.
     */
    raw: RunImprovementLoopResult<TArtifact, TScenario>;
}
/**
 * One-shot self-improvement loop. See module docstring for defaults +
 * extension points.
 *
 * @example Minimum:
 *
 *   const result = await selfImprove({
 *     agent: (surface, scenario, ctx) => myAgent(surface, scenario, ctx.signal),
 *     scenarios,
 *     judge,
 *     baselineSurface: DEFAULT_PROMPT,
 *   })
 *   console.log(`lift: ${result.lift.toFixed(3)} (${result.gateDecision})`)
 *
 * @example Distributed (workers in three regions):
 *
 *   await selfImprove({
 *     agent: httpDispatch({ resolveUrl: ({ placement }) => REGION_URLS[placement!] }),
 *     scenarios,
 *     judge,
 *     baselineSurface: DEFAULT_PROMPT,
 *     cellPlacement: ({ scenario }) => scenario.region,
 *     budget: { maxConcurrency: 12 },
 *   })
 */
export declare function selfImprove<TScenario extends Scenario, TArtifact>(opts: SelfImproveOptions<TScenario, TArtifact>): Promise<SelfImproveResult<TScenario, TArtifact>>;
//# sourceMappingURL=self-improve.d.ts.map