/** * Deterministic prompt relevance for selected skills. Pure metadata: it reads * slugs, aliases and trigger keywords, never payloads, and builds no regular * expression from profile data. * * - A keyword is a phrase: all of its words, in order and adjacent, in the * prompt. Duplicated keywords count once. * - A selection without keywords is matched by its slug's words as a phrase: * the whole slug, or a shorter run of adjacent slug words that carries the * slug's own distinguishing word ("seating plan" for event-seating-plan, not * "compliance check" for grant-compliance-check or "run of" for * live-event-run-of-show), scored by the longest run that matched. A shorter * run needs two words of at least SLUG_CONTENT_WORD_MIN_LENGTH letters and * one of the slug's least-used words in this profile's triggers. Single slug * words never match on their own, except a one-word slug. * - A one-word phrase counts only when it discriminates in this profile: a * word used by the triggers of more than DISCRIMINATING_WORD_MAX_SELECTIONS * selections (review, plan, check) says nothing on its own about which skill * a prompt needs. * - A selection is named when the prompt contains its kebab-case slug or alias * with at least one hyphen, or a one-word name separated only by whitespace * from the word "skill" or "skills". A name raises priority and lets the * selection's own one-word triggers count, but never selects on its own. * - A match much weaker than the prompt's best match (less than * WEAK_MATCH_FRACTION of its score) is marked weak: the prompt is about * something else, so it is offered as a load command, not injected. Named * selections are never weak. * - An empty keyword list still disables prompt matching. */ import type { ResolvedSkillSelection } from "../types/skill-selection.js"; /** A one-word trigger shared by more selections than this selects nothing alone. */ export declare const DISCRIMINATING_WORD_MAX_SELECTIONS = 3; /** One matched phrase word is worth this much; a candidate needs at least one. */ export declare const PHRASE_WORD_SCORE = 100; /** A match scoring below this fraction of the prompt's best match is weak. */ export declare const WEAK_MATCH_FRACTION = 0.5; /** Shorter slug words (of, to, a) neither distinguish a slug nor fill a partial slug run. */ export declare const SLUG_CONTENT_WORD_MIN_LENGTH = 3; export interface PromptRelevance { selection: ResolvedSkillSelection; /** 2 when the prompt names the selection, otherwise 1. */ priority: 1 | 2; score: number; /** The distinct phrases that counted, as normalized words. */ phrases: string[]; /** Much weaker than the prompt's best match; offered, not injected. */ weak: boolean; } export declare function promptWords(value: string): string[]; interface SelectionPhrases { phrases: string[][]; fromSlug: boolean; } /** The selection's distinct trigger phrases, or its slug's word runs when it has no keywords. */ export declare function selectionPhrases(selection: Pick): SelectionPhrases; /** How many selections use each word in any trigger phrase (each selection counted once). */ export declare function triggerWordFrequency(selections: readonly Pick[]): Map; /** * The slug's distinguishing words: among its words of at least * SLUG_CONTENT_WORD_MIN_LENGTH letters, those used by the fewest selections' * triggers in this profile (all of them when tied). */ export declare function slugAnchors(slugWords: readonly string[], frequency: ReadonlyMap): Set; /** * Rank selections by prompt relevance. Only candidates with at least one * counted phrase are returned, ordered by priority, then score, then slug. */ export declare function rankPromptRelevance(prompt: string, selections: readonly ResolvedSkillSelection[], frequency?: Map): PromptRelevance[]; /** At most this many weak prompt pointers are offered as load commands. */ export declare const PROMPT_OFFER_LIMIT = 3; export type PromptOfferReason = "partial-match" | "common-word"; export interface PromptOffer { selection: ResolvedSkillSelection; reason: PromptOfferReason; evidence: number; } /** * Selections the prompt points at too weakly to select, offered as `skills * load` commands and never injected. Only trigger keywords count, never slug * runs, and a selection the caller excludes (already selected, ranked or * loaded) is skipped. * * - partial-match: all content words (at least SLUG_CONTENT_WORD_MIN_LENGTH * letters, two or more) of a multi-word keyword appear in the prompt, though * not as the phrase, and one of them discriminates in this profile * ("designs review" in "push the screens to the designs app for review"). * - common-word: a one-word keyword used by more than * DISCRIMINATING_WORD_MAX_SELECTIONS selections appears in the prompt. * * Partial matches rank before common words, then more matching keywords, * then slug. A tie that does not fit the remaining offers is left out * entirely: an alphabetical slug is no reason to prefer one. */ export declare function rankPromptOffers(prompt: string, selections: readonly ResolvedSkillSelection[], frequency?: Map, exclude?: (selection: ResolvedSkillSelection) => boolean): PromptOffer[]; export {};