/** * centroid-router.ts — opt-in nearest-centroid agent router (ADR-527). * * Each agent label has one unit-length centroid: the mean MiniLM embedding of * its labelled example prompts (the ADR-391 corpus dev split, built by * `benchmarks/router/build-centroids.mjs`). A task goes to the label whose * centroid is most cosine-similar. When the top two scores are closer than * `margin`, the caller keeps the current router's pick instead. * * The artifact records the embedding model and dimension it was built with. * A query embedded any other way (for example MiniLM degraded to the hash * embedder) is never scored against it: `classify` returns `unavailable`. * * Gate: `CLAUDE_FLOW_ROUTER_CENTROID=1`. Off by default; the current router * is unchanged unless the flag is set. * * @module centroid-router */ export declare const CENTROID_ROUTER_ENV = "CLAUDE_FLOW_ROUTER_CENTROID"; export declare const CENTROID_MARGIN_ENV = "CLAUDE_FLOW_ROUTER_CENTROID_MARGIN"; export declare const CENTROID_ARTIFACT_ENV = "CLAUDE_FLOW_ROUTER_CENTROID_PATH"; export declare const CENTROID_SCHEMA = "ruflo.agent-centroids/1"; /** Label meaning "no agent fits"; the router abstains instead of picking one. */ export declare const ABSTAIN_LABEL = "none"; export interface CentroidArtifact { schema: typeof CENTROID_SCHEMA; /** Embedder kind the centroids live in. Only 'minilm' is built today. */ embedder: 'minilm'; /** Embedding model id reported by the local embedder when the artifact was built. */ model: string; dim: number; /** Default top-two margin below which the caller falls back. */ margin: number; /** sha256 of the corpus file the centroids were built from. */ corpusSha256: string; split: string; labels: string[]; /** Examples per label, aligned with `labels`. */ support: number[]; /** Unit-length centroids, aligned with `labels`. */ centroids: number[][]; } export type CentroidDecision = { status: 'decided'; label: string; score: number; runnerUp: string; runnerUpScore: number; margin: number; } | { status: 'fallback'; label: string; score: number; runnerUp: string; runnerUpScore: number; margin: number; reason: string; } | { status: 'unavailable'; reason: string; } /** A learned route (AgentDB or a persisted SONA pattern) answered before the centroid router ran. */ | { status: 'bypassed'; reason: string; }; export declare function centroidRouterEnabled(env?: NodeJS.ProcessEnv): boolean; /** Margin from the env when it is a finite number in [0, 1], else the artifact default. */ export declare function resolveMargin(artifact: Pick, env?: NodeJS.ProcessEnv): number; /** Throws with a specific message when the artifact is malformed. */ export declare function validateArtifact(a: unknown): CentroidArtifact; /** Load (and cache) the artifact. Returns the error instead of throwing. */ export declare function loadCentroidArtifact(env?: NodeJS.ProcessEnv): { artifact: CentroidArtifact | null; error: string | null; path: string; }; /** * Score one query embedding. * @param query the query vector (any length; normalised here) * @param queryEmbedder the embedder that actually produced `query` * @param queryModel the model id that produced it, when known */ export declare function classify(artifact: CentroidArtifact, query: ArrayLike, queryEmbedder: string, queryModel: string | undefined, margin: number): CentroidDecision; /** Test hook. */ export declare function __resetCentroidRouterForTests(): void; //# sourceMappingURL=centroid-router.d.ts.map