/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * @file The harvest side of the sub-venue lexicon: what one row of a harvestable source looks like, * how a file of them is read back, and what a pass over them extracts — attested surfaces plus the * measured shape of each designator's identifier half. * * {@link SubVenueHarvestRow} is SOURCE-NEUTRAL, and verified so: an Overture Places row from the * `airport_terminal` category is `{ designatorID, name }` and fits unchanged. It is declared here * rather than imported so the builder does not take a dependency on `@mailwoman/osm` (which * `@mailwoman/corpus` does not depend on) just to name a shape it reads from a file. * * Two measurements shape {@link extractAttestedPhrases}, and both are the reason it is safe to run * over raw OSM at all: * * **A feature's `name` is usually the VENUE's name, not a sub-venue phrase.** On the Berlin extract * (2,060 matched features) a `railway=platform` is named `Stendaler Straße` and an `amenity=university` * is named `Hertie School`; across 250,116 named Great Britain features only 6,003 (2.40%) contain a * designator token at all. So names are not harvested wholesale — a name contributes only when it * CONTAINS a phrase already in the surface index, which is what makes `Terminal E (Untere Ebene)` * evidence and `Otto Lilienthal Flughafen Berlin Tegel` not. * * **A matched phrase belongs to the record the PHRASE names, not the record the ROW carries.** * Attributing every hit to `row.designatorID` — the rule that matched the FEATURE — produced `west → * platform`, `hall → platform` and `biggin → platform` on the GB extract, because a bus stop tagged * `public_transport=platform` is named "Village Hall" or "West Kensington"; 108 of 133 OSM-derived * surfaces named a different record than the one they pointed at. Attribution therefore runs through * the index, and the row's own designator is kept as `context` — exactly the axis a confound board * needs, since a `hall` seen on a platform is a confound and a `hall` seen on a terminal is evidence. */ import { type SurfaceIndex } from "#tools/sub/venue/surfaces"; import type { IdentifierShape, SubVenueSurface } from "#tools/sub/venue/table"; /** * One row of a harvestable source, as read back off JSONL or out of a layer database. * * SOURCE-NEUTRAL by design, and verified so in wave 2: an Overture Places row from the `airport_terminal` category is * `{ designatorID, name }` and fits unchanged. What did NOT fit was the harvest function's hardcoded `osm:name` source * stamp — see `overture-subvenue.ts`'s docstring. Declared locally so the builder does not import `@mailwoman/osm` * (which `@mailwoman/corpus` does not depend on) just to name a shape it reads from a file. */ export interface SubVenueHarvestRow { /** * The designator the SOURCE's rule assigned to the FEATURE. Not necessarily the record a matched phrase names — see * this file's header on phrase attribution. Carried into {@link SubVenueSurface.context}. */ designatorID: string; /** * `venue` (station, airport, campus) or `sub_venue`, when the source's rule assigns one. The harvest itself does not * read it; the sub-venue slice recipe fills its venue slot from it. */ tier?: string; name?: string | null; ref?: string | null; localizedNames?: Record; } /** * Classify an OSM `ref` into an {@link IdentifierShape} class. * * The classes are the ones Berlin's gates actually produced, plus the two aviation forms the corpus task names * (`Terminal 2F` is digit-letter, `Concourse B` is letter). `range` covers both separators OSM uses for a gate serving * more than one stand: `16-18` and `0/1`. */ export declare function classifyIdentifier(ref: string): string; /** * Options for one harvest pass — which source stamp its surfaces carry and which region they were attested in. * * Both default to the OSM/unknown-region values wave 1 hardcoded, so an existing caller is unchanged. */ export interface HarvestOptions { /** * Source family: `osm` yields `osm:name` / `osm:name:`, `overture` yields `overture:name`. */ source?: string; /** * ISO 3166-1 alpha-2 of the extract or partition. `""` when unknown. */ region?: string; } /** * Harvest attested phrases and identifier shapes out of a source's rows. * * `index` gates the name harvest — a name contributes only when it CONTAINS a phrase already in the table. That filter * is the whole reason this function is safe to run over raw OSM: see this file's header for the Berlin measurement that * motivated it. The index also decides ATTRIBUTION: a hit is a surface of the record the PHRASE names, and the row's * own designator is recorded as `context`. * * Returns surfaces with real `observations` counts, so the lexicon can rank `terminal` above a phrase attested once. */ export declare function extractAttestedPhrases(rows: Iterable, index: SurfaceIndex, options?: HarvestOptions): { surfaces: SubVenueSurface[]; identifierShapes: IdentifierShape[]; }; /** * Read a JSONL file of {@link SubVenueHarvestRow}s. Blank lines and unparseable rows are skipped rather than fatal — an * extract is a build output, and one malformed line should not cost the whole lexicon. */ export declare function readSubVenueJSONL(path: string): Promise; //# sourceMappingURL=harvest.d.ts.map