/**
 * MemPalace text search — tokenized, field-weighted scoring.
 *
 * Design goals:
 *   1. Zero dependencies (no FTS index, no embedding model)
 *   2. Reasonable ranking out of the box: title-ish fields outrank body
 *   3. Tolerant to short queries (single keyword should still rank well)
 *   4. Tolerant to plural / case variations via simple stemming
 *
 * We tokenize on non-alphanumeric, lowercase everything, drop tokens
 * shorter than 2 chars and a small stopword list, and score each drawer
 * by summing per-token field weights:
 *
 *   tags     × 4   (semantic tags are the strongest signal)
 *   room     × 3
 *   wing     × 2
 *   content  × 1   (matches anywhere in body)
 *
 * Importance acts as a multiplier on the final score so the user can
 * boost high-signal drawers via the importance field. Recency also
 * lightly boosts via a half-life of 90 days.
 *
 * This is good enough until the store gets large; the search() entry
 * point is the swap-in for a real FTS / embedding search later.
 */
import type { Drawer, SearchOptions, SearchHit } from './types.js';
/**
 * Tokenize a string into lowercase, deduplicated, non-stopword tokens of
 * length ≥ 2. Very lightweight stemming: trailing 's' is stripped to fold
 * "drawer"/"drawers" together. Aggressive stemming (Porter, etc.) would
 * cost a lot for marginal recall gains at this scale.
 */
export declare function tokenize(s: string): string[];
/**
 * Top-level search. Filters by scope/wing/room/tags first, then scores
 * each remaining drawer and returns the top `limit` by score.
 */
export declare function searchDrawers(drawers: Drawer[], query: string, opts?: SearchOptions): SearchHit[];
