/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * `runPipeline` — the runtime coordinator that composes all six stages. * * Generic over stage implementations (see `types.ts::RuntimePipelineStages`). Each stage is * injected; the coordinator handles composition, timing, fast-path routing, and graceful * degradation when stages are absent. * * Implementation contract per `docs/engineering/reference/STAGES.md`. */ import type { AddressTree } from "../decoder/types.ts"; import type { FSTMatcherLike, PhraseProposal, PipelineOpts, PipelineResult, RuntimePipelineStages } from "./types.ts"; /** * Anchor weight for the coarse-placer's country prior (#244). Lower than the postcode anchor's 2.0 default — a * whole-string country guess is a broader, softer signal than a postcode that pins the country, so it blends more * gently with the candidate score. */ export declare const COARSE_PLACER_ANCHOR_WEIGHT = 1; /** * #743/#194 coverage guard: countries whose candidate gazetteer is complete enough that hard-filtering is a PURE WIN — * measured hard-resolve-rate ≥ 95% on held-out OpenAddresses points, so a hard-filter "miss → unresolved" is rare and * almost always a genuine non-match, not a coverage gap. A confident placement OUTSIDE this set stays on the SOFT * prior, so the low-coverage tail (FI/PL/…) keeps its recall until its gazetteer is filled (#193) — the win for covered * countries, no recall regression for the rest (DeepSeek-advised, 2026-06-22). * * FALLBACK ROLE (survey candidate #2, 2026-07-26): this set is now the FALLBACK for gazetteer artifacts that predate * the coverage manifest. Facts about the artifact live IN the artifact — the candidate gazetteer's `country_coverage` * table carries the per-country promote-gate verdicts + the measured rates (the numbers that used to be trivia in this * comment), and a loaded artifact's derived safelist (`resolver.artifactCoverage.hardCountrySafelist`) takes precedence * over this constant. The measured record lives in `mailwoman/gazetteer-pipeline/coverage-manifest.ts` * (MEASURED_COUNTRY_COVERAGE — grow THAT at promotes; it updates the artifact at rebuild). Precedence: per-call * `PipelineOpts.hardCountrySafelist` (the eval's instrument, measures ungated to grow the list) → the loaded artifact's * manifest → this constant. Historical receipts now recorded structurally in MEASURED_COUNTRY_COVERAGE: US/FR/DE 100, * ES 99.8, NL 97.3, IT 96.8 (in); FI 69.5, PL 77.8 (measured, out); GB + CA at the #928 promote (2026-07-06, OSM * panels, night 34); AU with the #244 placer class (2026-07-06). */ export declare const HARD_PLACE_COUNTRY_SAFELIST: ReadonlySet; /** * #912 lever 1 — is this parse a single BARE locality ("Paris", "Dublin")? The coarse placer is out-of-distribution on * one-token city names (trained on full addresses): measured on the gauntlet's bare-namesake rows it emitted Paris→IT * .35, Melbourne→GB .66 — all wrong, and even sub-threshold the SOFT posterior still re-ranks the resolver toward the * wrong country. A bare locality carries no country evidence the placer can read that the resolver's exact-tier + * population ranking doesn't already use better — so both production placeCountry call sites (the runtime pipeline and * `geocodeAddress`) ABSTAIN on this shape. Any second non-empty component makes the input address-shaped and the placer * runs as before. */ export declare function isBareLocalityTree(tree: AddressTree): boolean; /** * #1589's sibling of the #912 guard: true when the tree's ONLY value-bearing node is a `postcode`. * * A bare postcode under a locale-inferred country scope is the same disaster shape as a bare locality: `SW1A 1AA` under * the default en-US locale gets a HARD `defaultCountry: "US"` that filters the GB postalcode row the gazetteer holds, * and the query resolves to nothing — while the identical query under `--locale en-GB` answers 38 m from the rooftop. * The postcode's own FORMAT is harder evidence than the locale hint (the #928 table's premise), so the caller withholds * the inferred scope for this shape when the format implies countries that exclude it. */ export declare function isBarePostcodeTree(tree: AddressTree): boolean; /** * #743/#194: the shared coverage-guard gate — decide whether a confident coarse-placer country should become a HARD * candidate filter. Exported so the two production placeCountry call sites (the runtime pipeline AND `geocodeAddress`) * apply the SAME three gates and can't drift: confidence ≥ {@link HARD_PLACE_COUNTRY_MIN_CONF}, country in the safelist * (override or the default {@link HARD_PLACE_COUNTRY_SAFELIST}), and no caller-set hard/default country to respect. * Returns the country to hard-filter, or `undefined` to stay on the soft prior. * * `safelist` precedence is the CALLER's job: pass `perCallOverride ?? resolver.artifactCoverage?.hardCountrySafelist` * (the eval instrument first, then the loaded artifact's own manifest) and this gate falls back to the code constant * only when both are absent — byte-identical to the pre-manifest behavior. */ export declare function hardCountryFor(placedCountry: string, placedConfidence: number, existing: { hardCountry?: string; defaultCountry?: string; }, hardPlaceCountry: boolean | undefined, safelist: ReadonlySet | undefined): string | undefined; /** * Run the runtime pipeline. * * Composition order (per STAGES.md): * * 1. Normalize (or identity) * 2. Compute QueryShape (or empty) * 3. Locale gate (or caller-trust) * 4. Kind classifier (or default structured_address) * 5. Branch: fast-path → resolver; full → classifier → resolver * * Per-stage timing recorded on `result.timing`. Fast-path stages are absent from the timing map. */ export declare function runPipeline(raw: string, stages: RuntimePipelineStages, opts?: PipelineOpts): Promise; /** * The street-context gate pair (#1315): when BOTH the gazetteer FST and the street-morphology matcher are wired, the * classify call passes the matcher in with the morphology EMISSION prior zeroed — the gate alone (measured golden-flat, * fragment-positive) without the emission prior (measured US-golden −48). Absent either matcher, the spread is `{}` and * the decode is byte-stable. */ export declare const ZEROED_MORPHOLOGY_OPTS: { readonly biasScale: 0; readonly dependentLocalityPenalty: 0; }; /** * D2 remediation (#1320, ROAD_TO_MAILWOMAN_V8_1_0 §5.2): the pipeline ships the gate at FULL suppression (0.0), not the * classifier's 0.25 default. Measured 2026-07-26 on v8.0.0-as-shipped (branch TS == origin/main, FST md5 == published): * 0.0 puts FR admin-street-homonym at EXACT P0 parity (159/400 vs 157 at 0.25) with golden us/fr and every other * fragment class byte-identical to 0.25 — the "some admin mass for the semi-markov decoder" rationale for 0.25 carried * no measured benefit at the pipeline level. Satisfies the D-rule (iron rule 6) ≥P0 clause for #1318. */ export declare const STREET_CONTEXT_POSITIVE_SCALE = 0; export declare function streetContextGateFor(stages: { fst?: FSTMatcherLike; streetMorphology?: FSTMatcherLike; }): { fstStreetMorphology?: FSTMatcherLike; fstStreetMorphologyOpts?: { biasScale: number; dependentLocalityPenalty: number; }; fstStreetContextPositiveScale?: number; }; /** * Post-classification audit: for each phrase-grouper proposal whose span is entirely unlabeled (all-O) in the * classifier output, inject a provisional node using the grouper's structural hypothesis. This rescues spans the neural * model couldn't type — primarily venue text. * * The audit once took a classifier top-k and deferred to it on an orphaned span, and once suppressed a duplicate * singleton tag. Both existed for the joint-reconcile path, which fed the only top-k that ever reached here and was * removed in #1749; on the surviving argmax path the parameter was always `undefined`, so neither branch could fire. * Removed rather than left as unreachable code — the #425 reasoning they encoded is in the retirement report. */ export declare function grouperAudit(tree: AddressTree, proposals: PhraseProposal[], text: string): AddressTree; //# sourceMappingURL=runtime-pipeline.d.ts.map