/**
 * Embedder pre-filter for skill candidate selection (Phase 3 Task 3.3).
 *
 * Purpose: given a task subject string and a flat list of skills, rank
 * skills by cosine similarity between the subject embedding and each
 * skill's prose embedding, then return the top-K. The router (Task 3.4)
 * consumes this shortlist — the LLM classifier sees ~10 skills instead
 * of every skill in every pack, which keeps the prompt tractable and
 * the per-task token cost bounded.
 *
 * Two-tier design (per `project_opensquid_reduced_context_first_principle`
 * — "less in context = less drift"): the embedder is the cheap filter,
 * the model-aliased classifier is the expensive sort. Top-K of cosine
 * recall is sufficient because the classifier handles precision; we
 * deliberately bias toward recall here.
 *
 * Failure mode is "fall through to load-everything" — if Ollama is
 * unreachable, returning every skill is the correct behavior. The
 * router then re-filters via `fast_classifier`, or, in the worst
 * case (both unavailable), the runtime loads every skill, which is
 * the same condition you'd be in WITHOUT this layer. That's the
 * design ladder: each layer is an optional optimization, not a gate.
 *
 * Cache contract: callers supply a `Map<string, number[]>` keyed by
 * the prose string used to embed. The cache is content-addressed —
 * if a skill's prose changes, the new key won't hit, the new vector
 * gets stored, and the stale entry harmlessly stays in the map until
 * the caller decides to evict it. Phase 3 leaves invalidation to
 * consumers per the risk callout.
 *
 * Imports from: ../rag/ollama_client.js (the shared Ollama embed
 *   client used by the libsql RAG backend — single dependency point
 *   on the embedder), ./types.js (Skill type).
 * Imported by: src/runtime/index.ts (re-exported as `prefilterSkills`)
 *   and the dispatcher pipeline once Phase 3 wiring lands.
 */
import type { Skill } from './types.js';
export interface PrefilterOptions {
    k?: number;
    ollamaUrl?: string;
    cache?: Map<string, number[]>;
}
/**
 * Rank skills by embedding similarity to `taskSubject`; return top-K.
 *
 * Behavior:
 *  - Empty `skills`        → `[]` (cheap short-circuit).
 *  - Ollama unreachable on subject embedding → return ALL skills (fallback).
 *  - Ollama unreachable on a skill's embedding → skip that skill (still
 *    rank the rest). This is intentional asymmetry: a one-off skill
 *    fetch failure shouldn't blow up the whole rank, but if the very
 *    first call fails the embedder is presumed dead.
 *  - `k > skills.length`   → all (post-rank) skills.
 *
 * Cosine is computed inline (no extra dep). The formula's denominator
 * guards against zero-norm vectors by `|| 1` — that turns a degenerate
 * "embedded the empty string" case into a 0 score rather than NaN.
 */
export declare function prefilterSkills(taskSubject: string, skills: Skill[], opts?: PrefilterOptions): Promise<Skill[]>;
//# sourceMappingURL=skill_prefilter.d.ts.map