/** * Beta-bandit model routing with per-complexity-bucket priors (FU-4 learned * layer, ruflo ADR-142 pattern; E016's deterministic-config-first invocation * stays the layer below — this bandit only ever chooses AMONG candidates the * deterministic policy already approved). * * The ADR-142 property that matters: **failures on one task type do not * suppress a model globally.** Each (bucket, model) arm keeps its own * Beta(alpha, beta) posterior over "this model passes the gate for this * complexity". An unseen bucket falls back to the model's GLOBAL posterior * as its prior (hierarchical shrinkage), so a new bucket starts from * evidence, not from zero. * * Signal source: FU-5 telemetry. Only gated runs carry a pass/fail signal; * ungated runs are ignored by design (no verdict, no evidence). */ import type { FusionRunRecord } from "./types.js"; export type ComplexityBucket = "low" | "medium" | "high"; export interface BanditArm { alpha: number; beta: number; } export interface BanditRecommendation { modelId: string; bucket: ComplexityBucket; sample: number; pulls: number; reason: string; } /** Deterministic xorshift32 so tests are reproducible. */ export declare function xorshift32(seed: number): () => number; export declare class FusionBandit { private readonly rand; /** Global posteriors per model (all buckets pooled). */ private readonly global; /** Per-(bucket, model) posteriors. */ private readonly arms; constructor(seed?: number); private bump; /** * Learn from run records. `bucketOf` maps a run to its complexity bucket — * the caller owns complexity classification (deterministic, Inc 06 policy * signals); only gated runs carry a usable verdict. */ update(records: FusionRunRecord[], bucketOf: (r: FusionRunRecord) => ComplexityBucket): void; /** * Direct reward writeback for one (bucket, model) arm — the gate-outcome * feed (OK-9 W5, E017 reward loop). Same posterior shape as {@link update}: * the global arm and the per-bucket arm both move, so a failure informs but * does not convict the model in other buckets. `bucket` is the caller's * complexity vocabulary (low/medium/high today) — kept a plain string so * the routing facade's bucket strings key the same arms {@link recommend} * reads. */ noteOutcome(bucket: string, modelId: string, success: boolean): void; /** * Read one arm's posterior back (calibration/inspection — never on the * routing hot path). Falls back to the model's global arm when the bucket * is unseen, mirroring {@link recommend}'s hierarchical shrinkage; the * uniform prior when the model is entirely unseen. Returns a COPY. */ armFor(bucket: string, modelId: string): BanditArm; /** * Thompson-sample a recommendation among candidates for a bucket. Unseen * (bucket, model) arms start from the model's global posterior, so a * model's failures elsewhere inform but do not convict. */ recommend(bucket: ComplexityBucket, candidates: string[]): BanditRecommendation | undefined; } /** Build a bandit pre-loaded from the local runs log. */ export declare function loadBandit(bucketOf: (r: FusionRunRecord) => ComplexityBucket, seed?: number, logPath?: string): Promise; //# sourceMappingURL=bandit.d.ts.map