/** * output-verifier.ts — Confidence-gated tier escalation (post-generation). * * ADR-026/143 route tasks to a tier BEFORE generation. 2026 SOTA cascade * routing adds a post-generation gate: attempt the cheap tier, run a CHEAP * verifier over the produced output, and escalate to the next tier only when * the verifier is not confident. This module is that verifier. * * Design constraints (load-bearing): * - $0 by default — NO LLM call. Every signal is a structural / lexical * check: emptiness, refusal patterns, truncation, delimiter balance, * degenerate repetition, and (for code tasks) a real syntax parse via the * TypeScript compiler (lazy-imported; degrades to delimiter checks when * typescript is not installed) or JSON.parse for JSON output. * - Pure with respect to router state — recording the verdict into the * bandit's learning stream is the CALLER's job (the hooks_model-verify * MCP tool does it via ModelRouter.recordOutcome), keeping this module * trivially unit-testable. * - Escalation ladder mirrors the tier table: tier 2 (haiku) → tier 3 * (sonnet), sonnet → opus, opus has no bump (escalate=false even when the * verdict is not confident — the caller should retry or surface instead). * * Verdict semantics: `confident=false` means "cheap signals say this output * is likely unusable"; it is NOT a semantic-quality judgment. False * negatives (bad output that parses fine) are expected — this gate trades * recall for being free. * * @module ruvector/output-verifier */ export type VerifyTier = 1 | 2 | 3; export type VerifyModel = 'haiku' | 'sonnet' | 'opus'; export type VerifyTaskKind = 'code' | 'json' | 'text' | 'auto'; export interface VerifyInput { /** The task the output was generated for. */ task: string; /** The generated output to verify. */ output: string; /** Model that produced the output (drives the escalation ladder). */ model?: VerifyModel; /** Tier that produced the output; derived from `model` when absent. */ tierUsed?: VerifyTier; /** Force the task kind; 'auto' (default) detects from task + output. */ taskKind?: VerifyTaskKind; /** Minimum trimmed output length considered plausible (default 20). */ minLength?: number; } export interface VerifySignal { name: string; ok: boolean; detail?: string; } export interface VerifyVerdict { confident: boolean; /** Fraction of signals that passed (0..1). */ score: number; /** Human-readable failure reasons; empty when confident. */ reasons: string[]; /** Every signal evaluated, pass or fail. */ signals: VerifySignal[]; /** Tier the caller should use next: unchanged when confident, bumped 2→3 on failure. */ suggestedTier: VerifyTier; /** Concrete next model on the ladder (haiku→sonnet→opus); null when no bump exists. */ suggestedModel: VerifyModel | null; /** True when not confident AND a higher tier exists to escalate to. */ escalate: boolean; /** Detected task kind after 'auto' resolution. */ taskKind: Exclude; } interface ExtractedCode { lang: string; code: string; } /** Pull fenced code blocks out of markdown-ish output. */ export declare function extractCodeBlocks(output: string): ExtractedCode[]; /** Cheap stack-based bracket balance check that skips string/comment-ish content. */ export declare function bracketsBalanced(code: string): boolean; /** * Compute a confidence verdict for `output` from cheap structural signals, * and suggest an escalation target when not confident. */ export declare function verifyAndEscalate(input: VerifyInput): Promise; export default verifyAndEscalate; //# sourceMappingURL=output-verifier.d.ts.map