/** * Whole-word term matching, shared by the Brain's two rankers (#2062). * * `ComponentIndex.search()` and `scoreEntry()` both asked `haystack.includes(term)` * and dropped about twenty stopwords. Two faults compounded: * * - **Substrings.** `all` matched "c**all** to action", `line` matched * "time**line**", `end` matched "recomm**end**ed", `tab` matched "**tab**le". * - **Filler scored as signal.** `one`, `its`, `each`, `our`, `how` and `where` * all counted — and a `@useWhen` hit is the heaviest weight either ranker * gives. So a component scored for an ask simply by having ordinary English * in its criteria, and the more the catalog documented itself (#2051), the * worse routing got. * * The fix is deliberately small: compare **words**, folded for plurals, and * drop ordinary function words from the ask. No fuzzy matching, no synonyms — * those are #1563's job, and they need this floor under them first. * * Dependency-free on purpose: this file is in the hosted MCP's import graph, * which `scripts/verify-mcp-bundle.mjs` keeps lean. */ /** * Words that carry no ask. Function words (articles, pronouns, prepositions, * auxiliaries, conjunctions, quantifiers) plus the verbs people wrap a request * in — "I need…", "how do I build…", "we want to show…". * * Deliberately NOT here: numbers beyond "one" ("five or fewer options" is a * real criterion), "show" and "more" as tag words are handled by tag matching, * and domain nouns however common ("page", "form", "list"). */ export declare const STOPWORDS: ReadonlySet; /** * The verbs a request is wrapped in: "I need…", "how do I build…", "show how * much of an upload…". Dropped like stopwords — "show" was handing * `ed-show-more` a tag-name hit on every ask that began with it — with one * two exceptions: when they are ALL the ask has left ("show more" is how people * name that component, and an ask must never come back empty because its only * words were also verbs), and when one follows a determiner, where it is a * name rather than a verb ("a show more button"). */ export declare const REQUEST_WORDS: ReadonlySet; /** * Fold a plural onto its singular. Not a linguistic stemmer — it only has to * give the SAME answer for both sides of a comparison, so "series" → "sery" * is harmless: the haystack's "series" lands there too. */ export declare function stem(word: string): string; /** * Lowercased word tokens. Splitting on everything that is not a letter or a * digit also does the right thing with possessives ("person's" → "person" and * a stray "s") and hyphens ("sign-up" → "sign", "up"). */ export declare function tokenize(text: string): string[]; /** The set of folded words in `text`. */ export declare function stemsOf(text: string): Set; /** True when `term` appears in `text` as a whole word, plurals folded. */ export declare function hasTerm(text: string, term: string): boolean; /** * Tag names are identifiers, not prose, and partial matching is useful there: * "check" should find `ed-checkbox-field`. But only from the FRONT of a tag * word — "line" finding `ed-timeline` and "tab" finding `ed-table` were two of * the collisions that prompted this. A term shorter than four letters must * match a tag word exactly. */ export declare function tagMatches(tagName: string, term: string): boolean; /** * How well `term` matches a tag name: `1` for a whole tag word, `0.5` for the * front of one, `0` for neither. A prefix is weaker evidence — "check" is a * fair guess at `ed-checkbox-field`, but "mark" is a poor one at * `ed-p-marketing-checkout` — so the rankers give it half the weight. */ export declare function tagMatchStrength(tagName: string, term: string): 0 | 0.5 | 1; export declare function queryTerms(query: string): string[]; /** * The part of a `@notWhen` line that describes the situation being refused — * everything before the redirect. "the items are compared across attributes — * use `ed-table`, which lines figures up in columns" refuses *comparison*; the * words after the dash describe `ed-table`, and docking an entry for them would * punish it for naming its neighbour well. * * A line may hold several clauses ("… — use `ed-menu`; when it navigates — use * `ed-link-list`"), and a situation may carry its own parenthetical dashes * ("content — a photo, a screenshot — use `ed-image`"), so each `;` clause is * cut at its LAST dash that opens a redirect. A later clause with no redirect * of its own is the tail of the previous one's, and is dropped. A first clause * with none ("… — no Eddie layout does that; compose it…") falls back to its * first dash: what follows is commentary, not the situation. */ export declare function refusedSituation(notWhenLine: string): string; //# sourceMappingURL=term-match.d.ts.map