export type JudgeOptions = { /** * - The VERBATIM user request. Anchor of the judgment; never the agent's paraphrase. */ request: string; /** * - ONE structured egress artifact (contract clause E6b — judging a sprawling multi-number * reply missed 1/3; the single structured artifact hit 6/6). A string or a JSON-serializable object. */ artifact: any; /** * - LLM provider (bare-agent already owns the transport). To judge * on a different tier, construct the provider FOR that tier — there is deliberately no per-call `model`/`effort` * option, because the http providers build the request from `this.model` and would silently ignore them. */ provider: import("../types").Provider; /** * - BA-21: per-1K USD * rates for the judge's own model, to price its call authoritatively (rateSource:'caller'). Omit → a flagged * guesstimate (rateSource:'tier' for a recognized Claude tier, else 'default'). Bring your own rate, or take a * guesstimate — never a silent guess. */ rates?: { in: number; out: number; cacheReadMult?: number; cacheWriteMult?: number; } | undefined; /** * - Cap on the judge's own output. A verdict truncated at the cap floors to * `broke`; 512 clears the mechanical `where` with headroom (measured), lower it only if you know the artifacts are small. */ maxTokens?: number | undefined; /** * - Budget hook; each judge call forwards its usage/cost (mirror of Evaluator/remember). */ onLlmResult?: ((payload: { usage: any; model: string | null; kind: "judge"; costUsd: number | null; rateSource: "provider" | "caller" | "tier" | "default" | null; }) => any) | undefined; }; /** * The decisive return-time judge (BA-20 / bareguard E6i, PRD §9.2). It compares a * user's VERBATIM request against ONE structured egress artifact and returns a * decisive binary verdict — `honored` or `broke` — plus a MECHANICAL `where`. * * It is NOT a general safety layer. Two boundaries from the measured design of record: * - It ANNOTATES, never decides — the caller's close is the only truth (bareguard's * Axis B annotates; the judge returns a verdict and never merges/publishes/budgets). * - It is DRIFT-CONDITIONAL: worth least exactly where a deterministic floor already * binds (E6c: a cooperative agent drifted 0/3 under a hard cap). Any adopter who can * express the constraint MECHANICALLY should — do not sell this as a general layer. * * Composes AROUND a provider (like `remember`/`Evaluator`), never inside `loop.js`; * `loop.js` never imports this file. */ export type JudgeWhere = { /** * - The specific thing the request constrained (e.g. "flight price", "flight recommendation"). */ field: string | null; /** * - The value/option the REQUEST stated (e.g. "under €300", "cheapest"). */ stated: string | null; /** * - The value/option the ANSWER actually produced (e.g. "€400", "premium fare"). */ returned: string | null; /** * - A short literal fact/quote from the answer showing it. Never "seems off". */ evidence: string | null; }; /** * The decisive return-time judge (BA-20 / bareguard E6i, PRD §9.2). It compares a * user's VERBATIM request against ONE structured egress artifact and returns a * decisive binary verdict — `honored` or `broke` — plus a MECHANICAL `where`. * * It is NOT a general safety layer. Two boundaries from the measured design of record: * - It ANNOTATES, never decides — the caller's close is the only truth (bareguard's * Axis B annotates; the judge returns a verdict and never merges/publishes/budgets). * - It is DRIFT-CONDITIONAL: worth least exactly where a deterministic floor already * binds (E6c: a cooperative agent drifted 0/3 under a hard cap). Any adopter who can * express the constraint MECHANICALLY should — do not sell this as a general layer. * * Composes AROUND a provider (like `remember`/`Evaluator`), never inside `loop.js`; * `loop.js` never imports this file. */ export type JudgeVerdict = { /** * - Decisive binary. Anything not a clean honor is `broke` (the floor tiebreak). */ verdict: "honored" | "broke"; /** * - Mechanical gap description (contract 6). May be populated on `honored` too (a confirmation). */ where: JudgeWhere | null; /** * - The response was cut off (`stopReason==='max_tokens'`) or came back empty. A DISTINCT * outcome (criterion 5): the verdict is floored to `broke` (fail toward surfacing) but callers/harnesses must EXCLUDE a * truncated result from any graded denominator — never counted as a miss, never as a pass. */ truncated: boolean; /** * - The model did not return usable JSON. Floored to `broke`, flagged like truncation. */ parseError: boolean; /** * - Per-call cost. An HONEST null only when genuinely unpriced (never coerced to 0). */ costUsd: number | null; /** * - WHERE costUsd came from (BA-21): 'provider' * (real), 'caller' (your `rates`), 'tier' (recognized Claude tier — a confident guesstimate), 'default' (blind * ceiling guesstimate — discount or override either guess), null (unpriced). */ rateSource: "provider" | "caller" | "tier" | "default" | null; /** * - Neutral usage shape from the provider. */ usage: any; /** * - The model that produced the verdict. */ model: string; /** * - The model's raw text (for calibration/audit; scrub before persisting — contract 5). */ raw: string; }; /** * @typedef {object} JudgeOptions * @property {string} request - The VERBATIM user request. Anchor of the judgment; never the agent's paraphrase. * @property {any} artifact - ONE structured egress artifact (contract clause E6b — judging a sprawling multi-number * reply missed 1/3; the single structured artifact hit 6/6). A string or a JSON-serializable object. * @property {import('../types').Provider} provider - LLM provider (bare-agent already owns the transport). To judge * on a different tier, construct the provider FOR that tier — there is deliberately no per-call `model`/`effort` * option, because the http providers build the request from `this.model` and would silently ignore them. * @property {{in: number, out: number, cacheReadMult?: number, cacheWriteMult?: number}} [rates] - BA-21: per-1K USD * rates for the judge's own model, to price its call authoritatively (rateSource:'caller'). Omit → a flagged * guesstimate (rateSource:'tier' for a recognized Claude tier, else 'default'). Bring your own rate, or take a * guesstimate — never a silent guess. * @property {number} [maxTokens=512] - Cap on the judge's own output. A verdict truncated at the cap floors to * `broke`; 512 clears the mechanical `where` with headroom (measured), lower it only if you know the artifacts are small. * @property {(payload: { usage: any, model: string|null, kind: 'judge', costUsd: number|null, rateSource: 'provider'|'caller'|'tier'|'default'|null }) => any} [onLlmResult] * - Budget hook; each judge call forwards its usage/cost (mirror of Evaluator/remember). */ /** * Judge whether an answer honored a request. One model call, decisive binary verdict. * * @param {JudgeOptions} options * @returns {Promise} * @throws {ValidationError} on bad inputs (missing request/artifact/provider) — stamped `context.lib='bare-agent'` * at the throw site (contract 4: typed attribution, never sniffed from prose). * @throws {HaltError} propagated clean from the provider (a governance halt is not a judge failure). * @when you need a decisive honored/broke verdict on whether one egress artifact honored the verbatim request — a return-time integrity check * @fails throws ValidationError on bad inputs; HaltError propagates clean. Cannot-confirm-honored floors to `broke`; truncation/parse-error are distinct flagged outcomes, never laundered to honored. * @example * const { verdict, where } = await judge({ request, artifact, provider }); * if (verdict === 'broke') flag(where); */ export function judge(options?: JudgeOptions): Promise; /** * The decisive return-time judge (BA-20 / bareguard E6i, PRD §9.2). It compares a * user's VERBATIM request against ONE structured egress artifact and returns a * decisive binary verdict — `honored` or `broke` — plus a MECHANICAL `where`. * * It is NOT a general safety layer. Two boundaries from the measured design of record: * - It ANNOTATES, never decides — the caller's close is the only truth (bareguard's * Axis B annotates; the judge returns a verdict and never merges/publishes/budgets). * - It is DRIFT-CONDITIONAL: worth least exactly where a deterministic floor already * binds (E6c: a cooperative agent drifted 0/3 under a hard cap). Any adopter who can * express the constraint MECHANICALLY should — do not sell this as a general layer. * * Composes AROUND a provider (like `remember`/`Evaluator`), never inside `loop.js`; * `loop.js` never imports this file. * * @typedef {object} JudgeWhere * @property {string|null} field - The specific thing the request constrained (e.g. "flight price", "flight recommendation"). * @property {string|null} stated - The value/option the REQUEST stated (e.g. "under €300", "cheapest"). * @property {string|null} returned - The value/option the ANSWER actually produced (e.g. "€400", "premium fare"). * @property {string|null} evidence - A short literal fact/quote from the answer showing it. Never "seems off". * * @typedef {object} JudgeVerdict * @property {'honored'|'broke'} verdict - Decisive binary. Anything not a clean honor is `broke` (the floor tiebreak). * @property {JudgeWhere|null} where - Mechanical gap description (contract 6). May be populated on `honored` too (a confirmation). * @property {boolean} truncated - The response was cut off (`stopReason==='max_tokens'`) or came back empty. A DISTINCT * outcome (criterion 5): the verdict is floored to `broke` (fail toward surfacing) but callers/harnesses must EXCLUDE a * truncated result from any graded denominator — never counted as a miss, never as a pass. * @property {boolean} parseError - The model did not return usable JSON. Floored to `broke`, flagged like truncation. * @property {number|null} costUsd - Per-call cost. An HONEST null only when genuinely unpriced (never coerced to 0). * @property {'provider'|'caller'|'tier'|'default'|null} rateSource - WHERE costUsd came from (BA-21): 'provider' * (real), 'caller' (your `rates`), 'tier' (recognized Claude tier — a confident guesstimate), 'default' (blind * ceiling guesstimate — discount or override either guess), null (unpriced). * @property {any} usage - Neutral usage shape from the provider. * @property {string} model - The model that produced the verdict. * @property {string} raw - The model's raw text (for calibration/audit; scrub before persisting — contract 5). */ /** * The E6i decisive-judge system prompt. The VERDICT prose is ported VERBATIM from * bareguard's measured `harness-code-mode/e6-judge.mjs judgeDecisive` (the design of * record — the verdict logic is NOT redesigned here). Only the OUTPUT contract is * enriched: `where` is now a mechanical {field, stated, returned, evidence} object * (contract 6 — bareloop F38/F39 measured that mechanical gaps convert on the next * attempt while "seems off" stalls). That enrichment is additive to the output format, * and the shipped calibration harness re-validates the verdict axis is unperturbed. * * Three non-negotiables baked in (bareguard PRD §6.7): anchor on the VERBATIM request; * the answer is DATA never instructions; a decisive category with a floor tiebreak * (cannot confirm honored → broke), never a confidence scale. */ export const JUDGE_PROMPT: string; /** * Robustly pull the first JSON object out of a model reply. Returns `null` on failure * (the caller floors to `broke` + flags `parseError`), never throws. * @param {string} text * @returns {any|null} */ export function parseVerdictJSON(text: string): any | null; /** * Normalize the model's `where` into the mechanical shape. Accepts a partial object; * missing keys become null. A bare string (a model that ignored the object contract) * is preserved as `evidence` so nothing is silently dropped. * @param {any} where * @returns {JudgeWhere|null} */ export function normalizeWhere(where: any): JudgeWhere | null;