/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * Punctuation-gap span bridging — the v4.4.0 corrective (and the long-deferred Saint-Albans * span-merge, scoped to where it is provably safe). * * The corpus alignment tokenizer drops standalone punctuation (corpus/src/tokenize.ts), so NO * training row can label the periods inside "P.O. Box" — the model learns the tag perfectly * (every letter piece at 0.93+ confidence) but emits it as fragments split at each dot, and span * assembly surfaces only the first fragment ("p"). Measured on the v1.3.0 gate: dotted po_box * leaders failed 98%, ALL truncations, while plain leaders passed — a structural expressivity * limit of the label format, not a learning failure. * * The fix is deterministic: AFTER decode, merge adjacent same-label spans whose gap consists only * of punctuation/whitespace, contains at least one non-space character, and is short (≤ 3 chars). * The non-space requirement is essential — space-only gaps ("Saint Paul" as two locality spans) * are NOT bridged, because a space between two same-tag spans is often a real boundary (the * Saint-Albans fragmentation wants this fix too, but it must come with its own evidence; this * pass stays conservative by construction). * * Runs beside the postcode/unit repair passes in the classifier, before tree-building. */ import type { DecoderToken } from "@mailwoman/core/decoder"; /** * Options for {@link bridgePunctuationGaps}. */ export interface BridgePunctuationOpts { /** * Structural spans (from the Stage 2.7 span proposer — ANNOTATION/QUOTED groups, delimiters inclusive) whose * boundaries no merge may straddle: M2's crossing constraint, the bridge's mirror image (the bridge merges across * WEAK punctuation; this blocks merging across STRUCTURAL punctuation). A merge is blocked when either span boundary * falls inside the gap being bridged — e.g. an apostrophe-quoted name whose closing quote sits in an * otherwise-bridgeable gap. Boundaries already inside a labeled token are the model's call, not the bridge's; only * gaps are policed. */ blockedSpans?: ReadonlyArray<{ start: number; end: number; }>; } /** * Merge same-label fragments separated only by punctuation gaps. Returns a new token array where the first fragment of * each bridged group is widened to the group's full char range (so span extraction reads the raw text straight through * the punctuation), and later fragments are dropped. Labels, ordering, and all non-bridged tokens are untouched. */ export declare function bridgePunctuationGaps(text: string, input: readonly DecoderToken[], opts?: BridgePunctuationOpts): DecoderToken[]; //# sourceMappingURL=span-bridge.d.ts.map