/**
 * `judge()` — LLM-judge matcher, callable from inside a test body.
 *
 * Two ergonomic forms:
 *
 *   await judge(result, 'identifies the failing dependency');         // single claim
 *   await judge(result.trajectory, ['claim 1', 'claim 2']);            // legacy form
 *
 * Per-call options:
 *
 *   await judge(result, claim, { evaluatorId: 'system-rca-default' });
 *   await judge(result, claim, { model: 'claude-sonnet' });
 *
 * On evaluation, `judge()` records a MatcherResult and returns a
 * {@link Verdict} **without throwing** (RFC 004 §4.8). A failing
 * `gate`-role verdict still fails the test (the runner inspects the
 * recorded results), but the body keeps running so every signal is
 * collected. To hard-stop the body on a bad verdict, call
 * `(await judge(...)).orThrow()` or assert `expect(verdict).toPass()`.
 *
 * Two roles:
 *   - `judge(result, claim)`         — gate: a failing verdict fails the test.
 *   - `judge.observe(result, claim)` — observe: feeds score + insights only,
 *                                       never fails the test.
 *
 * Calls the Agent Health server's /api/judge endpoint with the same
 * payload shape (`{ trajectory, expectedOutcomes, modelId, evaluatorId }`)
 * the UI "Run Test" path uses, so SDK and UI runs are scored by the same
 * judge prompt and provider routing.
 *
 * Run-level evaluator default: the runner injects a bound version of
 * `judge` into `TestFixtures` via `bindJudge(run.evaluatorId)`. Code
 * that destructures `judge` from the fixture (`async ({ judge }) => ...`)
 * automatically picks up the run's evaluator with no per-call argument.
 * Code that imports `judge` from the package gets the unbound version
 * and must pass `evaluatorId` explicitly.
 */
import type { TrajectoryStep } from '../../types/index.js';
/** Whether a judge signal gates the test verdict or is observational only. */
export type JudgeRole = 'gate' | 'observe';
/**
 * The result of a `judge()` call. Carries the verdict data plus a few
 * convenience flags and an explicit hard-stop escape hatch. Returned
 * (never thrown) so the body can collect multiple verdicts; the recorded
 * MatcherResult is what actually gates the test.
 *
 * Backward-compatible with the old `JudgeVerdict` (same
 * `passFailStatus`/`accuracy`/`reasoning` fields).
 */
export interface Verdict {
    passFailStatus: 'passed' | 'failed';
    /** Headline accuracy on the [0, 100] interval. */
    accuracy: number;
    /** Normalised score on the [0, 1] interval (`accuracy / 100`). */
    score: number;
    /** Free-form judge reasoning. */
    reasoning: string;
    /** Convenience: `passFailStatus === 'passed'`. */
    pass: boolean;
    /** Role this verdict was produced with (`gate` or `observe`). */
    role: JudgeRole;
    /** True when the judge was skipped (no LLM call was made). */
    skipped: boolean;
    /** True when the judge could not run at all (endpoint error). */
    errored: boolean;
    /** Underlying error message when `errored` is true. */
    errorMessage?: string;
    /**
     * Hard-stop: throw if the verdict did not pass. A no-op for passing,
     * skipped verdicts. Returns the verdict so it can be chained:
     *   const v = (await judge(result, claim)).orThrow();
     */
    orThrow(): Verdict;
}
/** @deprecated Use {@link Verdict}. Retained as a structural alias. */
export type JudgeVerdict = Verdict;
/**
 * Per-call options for the SDK `judge()` matcher. Mirrors the relevant
 * fields of the `/api/judge` request body so SDK runs and UI runs use
 * the same judge prompt + evaluator + provider routing.
 */
export interface JudgeOptions {
    /**
     * Override the agent-health server URL. Defaults to
     * `http://localhost:${AGENT_HEALTH_PORT ?? 4001}`.
     */
    serverUrl?: string;
    /**
     * Override the judge model. Forwarded as `modelId` on the request body;
     * the server resolves it through `config.models[modelId]` exactly as it
     * does for UI runs.
     */
    model?: string;
    /**
     * Stored evaluator id (system or user). Forwarded as `evaluatorId` on
     * the request body. The server resolves system evaluators via
     * `getSystemEvaluatorById(...)` and user evaluators via
     * `storage.evaluators.getById(...)` — identical to the UI path. Falls
     * back to the default evaluator when omitted on both call and bind.
     */
    evaluatorId?: string;
    /**
     * Skip the LLM call entirely. The judge returns a non-gating `skipped`
     * verdict (pass: true, skipped: true). Useful for fast/offline iteration.
     * The global `AH_SKIP_JUDGE=1` env var forces this for every judge call.
     */
    skip?: boolean;
}
/** Clear the in-process judge verdict cache (test isolation / new run). */
export declare function clearJudgeCache(): void;
export declare function wasJudgeCalled(): boolean;
export declare function resetJudgeFlag(): void;
interface ResultLike {
    trajectory?: TrajectoryStep[];
    finalResponse?: () => string;
    agentOutput?: string;
    runId?: string;
}
/**
 * The callable `judge` surface: a function (gate role) with an `.observe`
 * method (observe role).
 */
export interface JudgeFn {
    (resultOrTrajectory: ResultLike | TrajectoryStep[], claimOrClaims: string | string[], options?: JudgeOptions): Promise<Verdict>;
    /**
     * Observational judge: records the verdict for score + insights but does
     * NOT gate the test (a failing observe verdict never fails the run).
     */
    observe(resultOrTrajectory: ResultLike | TrajectoryStep[], claimOrClaims: string | string[], options?: JudgeOptions): Promise<Verdict>;
}
/**
 * Single-claim ergonomic form (gate role).
 * @example
 *   const v = await judge(result, 'identifies the failing dependency');
 *   if (!v.pass) { ... }                       // non-throwing
 *   (await judge(result, claim)).orThrow();      // explicit hard-stop
 *   await judge.observe(result, claim);          // score-only, never gates
 */
export declare const judge: JudgeFn;
/**
 * Bind run-level defaults to `judge` and return a callable with the same
 * signature. Used by the SDK runner to inject `run.evaluatorId` (and
 * optionally a default judge model) into the `TestFixtures.judge` slot,
 * so test bodies that destructure `({ judge })` automatically inherit
 * the run's evaluator selection — matching the UI's behaviour where the
 * evaluator picked on the run config applies to every judged test case.
 *
 * Per-call options always win over the bound defaults; pass an empty
 * object (or omit the field) to fall through to the bound value.
 *
 *   const boundJudge = bindJudge({ evaluatorId: run.evaluatorId });
 *   await boundJudge(result, claim);                                  // uses run.evaluatorId
 *   await boundJudge(result, claim, { evaluatorId: 'other' });        // overrides
 *   await boundJudge(result, claim, { evaluatorId: undefined });      // still uses bound default
 */
export declare function bindJudge(defaults?: {
    evaluatorId?: string;
    model?: string;
    serverUrl?: string;
    skip?: boolean;
}): JudgeFn;
export {};
//# sourceMappingURL=judge.d.ts.map