/** * THE handle grammar — byte-identical to MENTION_RE's `@` branch * (src/render/ui/mention.ts, the E34 composer's tokenizer), pinned by test: * what the mention editor treats as one deletable tag is exactly what the * index extracts, or the two surfaces would disagree about what a mention IS. */ export declare const MENTION_HANDLE_RE: RegExp; /** One extracted mention, as IR (design §2.6). `handle` is the portable * identity (lowercased, no `@`) — vocabulary is case-insensitive everywhere * else in the engine (the enum check, personLookupOf), so `@Felipe` in * prose and `felipe` in a directory are one person here too. `raw` keeps * the author's bytes; `context` is the trimmed source line (≤200 chars), * the content half of the content-derived read-state key (owner.ts). */ export interface MentionIR { handle: string; raw: string; context: string; /** prose = a paragraph's @handle · cell = an @handle inside any cell text * · person = a person-typed column's VALUE, the strongest mention, which * carries no `@` at all */ source: 'prose' | 'cell' | 'person'; /** prose only: the `## heading` the line sits under (null = preamble) */ section?: string | null; /** cell/person only: the owning row's address (L13's OwnerSource shape) */ block?: string; row?: string; uuid?: string; column?: string; } /** What the text scanner alone can know — the caller supplies source and * owner fields, because only it knows whether the text was a paragraph, a * cell, or (in the cloud) a comment body. One hit shape for all three is * what keeps the conversational scan (`mention_live`, PR3/PR7) the same * extractor instead of a parallel one. */ export interface MentionHit { handle: string; raw: string; context: string; } /** * Every @handle in a text, with the media scanner's hygiene (§2.6): * · fence-masked — a `@decorator` in a code block is code, not a person; * · inline code stripped per line — `@handle` in backticks is an example; * · table rows skipped (a line whose first ink is `|`) — those bytes are * the CELL scanner's territory, and scanning them as prose would index * every cell mention twice (the one dedupe rule L11 exists to protect); * · an `@` glued to the email charset on its LEFT is an email's domain * half, not a mention — `felipe@subdial.com` mentions nobody, and * without this guard every email in prose would mint a phantom handle * for its domain. The guard reuses the regex's own `[\w.-]` vocabulary, * so what can END a handle is exactly what refuses to PRECEDE one; * · trailing `.`/`-` runs are SENTENCE PUNCTUATION, not identity — * "Ask @zoe." mentions zoe, and without this trim the phantom handle * "zoe." would slip past every handle-keyed consumer (`dj mentions * --handle zoe`, mention_seen keys, the inbox fan-out) as silently * dropped notifications. In the E34 composer the same bytes were a * harmless tokenization quirk (a deletable tag with a dot); once * handles are DATA the quirk costs deliveries. The trim lives HERE, on * the extraction side beside the email guard, so the pinned regex * bytes — and the composer's tokenization — stay untouched, and `raw` * keeps the author's bytes for display. Interior dots survive * (`@zoe.bar` is one handle); a handle that trims to nothing (`@...`) * mints no mention at all. * Returns hits in document order. Never throws, never reports: extraction * is data (§6). */ export declare function scanMentions(text: string): MentionHit[]; /** * THE SEVEN QUERY FIELDS (design §5 PR9): MentionIR minus its two free-text * members — `raw` is the author's bytes and `context` a whole source line, * neither a vocabulary a filter should equality-match. Everything else is * addressable: who (handle), how (source), and where (section · block · row · * uuid · column). */ export declare const MENTION_QUERY_FIELDS: readonly ["handle", "source", "section", "block", "row", "uuid", "column"]; /** One mention entry as a query context: the seven fields, absent-as-'' (the * ''-not-NULL convention every mention table already keeps). Total over * whatever arrives — payload entries, door entries and raw MentionIR all * carry these keys or fewer. */ export declare function mentionQueryCtx(m: Partial> | null | undefined): Record; /** Does this query speak `@me` at all? The client asks BEFORE compiling: with * no viewer a query that speaks @me is dead — it must show the sign-in empty * state (0020: no viewer means NOBODY, never everybody), not filter on the * literal bytes. */ export declare function queryMentionsMe(src: string): boolean; /** Every `@me` token replaced by a QUOTED literal of `handle` — the spelling * the query lexer accepts whatever the handle contains. The bake validates * with a placeholder handle; the client fills the viewer's real one * (viewerHandle()) — same substitution, one grammar. */ export declare function fillMeInQuery(src: string, handle: string): string; /** * A person-typed cell's handles — `felipe` / `@felipe` / `felipe, maria` — * as (handle, raw) pairs. SAME split as personchip.ts's `personHandles` * (comma/whitespace separators, leading `@` tolerated and stripped), pinned * by a parity test rather than an import: personchip rides the client * bundle and must stay free-standing there, while this side additionally * lowercases into MentionIR's handle contract. An Assignee value is the * strongest mention there is and carries no `@` — which is exactly why the * @-scanner above cannot serve person columns and this splitter exists. */ export declare function splitPersonCell(raw: string): { handle: string; raw: string; }[];