@mailwoman/corpus 10.3.0 → 10.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -17
- package/data/PROVENANCE.md +287 -273
- package/data/address-source-register.json +545 -23
- package/data/license-decisions.json +120 -0
- package/data/licenses/PROVENANCE.md +5 -5
- package/data/licenses/cdla-permissive-2.0.md +6 -6
- package/data/licenses/geonames-publication.md +5 -5
- package/data/licenses/licence-ouverte-2.0.md +3 -3
- package/data/licenses/national-address-database.md +12 -12
- package/data/licenses/nlod-2.0.md +3 -3
- package/data/licenses/sirene-publication.md +13 -6
- package/data/licenses/whosonfirst-licenses.md +4 -4
- package/data/source-resolutions.json +46 -0
- package/data/training-manifests/v0.7.2-address-systems.effective.json +1169 -0
- package/data/training-manifests/v0.7.2-address-systems.json +550 -0
- package/lib/adapters/cordis/adapter.ts +9 -9
- package/lib/adapters/gleif/adapter.ts +7 -8
- package/lib/adapters/po-box/adapter.ts +1 -1
- package/lib/adapters/source-id.ts +1 -1
- package/lib/adapters.ts +4 -2
- package/lib/au/adapters/gnaf/adapter.ts +1 -1
- package/lib/be/adapters/brussels/adapter.ts +3 -3
- package/lib/be/adapters/vlaanderen/adapter.ts +1 -1
- package/lib/be/adapters/wallonie/adapter.ts +1 -1
- package/lib/build/align.ts +1 -1
- package/lib/build.ts +1 -1
- package/lib/cz/adapters/cuzk/adapter.ts +2 -2
- package/lib/cz/tools/fetch/cuzk.ts +6 -6
- package/lib/de/recipes/locale.ts +1 -1
- package/lib/dk/adapters/inspire/adapter.ts +1 -1
- package/lib/ee/tools/fetch/ads.ts +2 -2
- package/lib/es/adapters/bizkaia/adapter.ts +1 -1
- package/lib/es/adapters/navarra/adapter.ts +2 -2
- package/lib/es/cadastre.ts +2 -2
- package/lib/es/tools/fetch/bizkaia.ts +8 -8
- package/lib/es/tools/fetch/catastro.ts +6 -6
- package/lib/es/tools/fetch/navarra.ts +4 -4
- package/lib/fingerprints.ts +3 -3
- package/lib/fr/adapters/finess/adapter.ts +6 -5
- package/lib/fr/adapters/finess/voie-type.ts +1 -1
- package/lib/fr/tools/fetch/annuaire-education.ts +3 -3
- package/lib/gb/adapters/os-open/adapter.ts +453 -0
- package/lib/gb/constituent-country.ts +52 -0
- package/lib/gb/os-open/nearest-link.ts +169 -0
- package/lib/gb/os-open/open-names.ts +180 -0
- package/lib/gb/os-open/open-roads.ts +145 -0
- package/lib/gb/tools/fetch/os-open.ts +251 -0
- package/lib/inspire/address.ts +3 -3
- package/lib/international/recipes/locale.ts +41 -7
- package/lib/it/adapters/anac/adapter.ts +4 -3
- package/lib/jp/adapters/wof-admin/adapter.ts +2 -2
- package/lib/kr/adapters/juso/label-rows.ts +1 -1
- package/lib/kr/adapters/localdata/key-index.ts +2 -1
- package/lib/lu/adapters/bd-adresses/adapter.ts +1 -1
- package/lib/nl/adapters/kadaster/adapter.ts +2 -2
- package/lib/nl/tools/fetch/kadaster.ts +2 -2
- package/lib/parquet/shuffle.ts +2 -2
- package/lib/parquet/span-sql.ts +8 -6
- package/lib/parquet/streams.ts +1 -1
- package/lib/parquet/writers.ts +2 -2
- package/lib/pl/tools/fetch/emuia.ts +2 -2
- package/lib/recipes/scaffold.ts +2 -2
- package/lib/recipes/sources.ts +3 -3
- package/lib/recipes/sub/venue/render.ts +1 -1
- package/lib/recipes/sub/venue/sources.ts +4 -3
- package/lib/recipes/sub/venue.ts +4 -3
- package/lib/recipes/venue.ts +11 -11
- package/lib/registers.ts +7 -0
- package/lib/ro/adapters/retea-scolara/adapter.ts +2 -2
- package/lib/runner.ts +3 -3
- package/lib/sk/tools/fetch/inspire.ts +3 -3
- package/lib/source-register/effective-manifest.ts +14 -8
- package/lib/source-register/training-manifest.ts +30 -2
- package/lib/source-register/types.ts +2 -2
- package/lib/source-register.ts +1 -0
- package/lib/subvenue/harvest.ts +6 -5
- package/lib/subvenue/promotions.ts +3 -3
- package/lib/subvenue/surfaces.ts +1 -1
- package/lib/subvenue/table.ts +6 -6
- package/lib/surfaces/locale.ts +1 -1
- package/lib/synthesizers/anchor-absorption.ts +1 -1
- package/lib/synthesizers/boundary-stress.ts +3 -2
- package/lib/synthesizers/no-street.ts +1 -1
- package/lib/synthesizers/po-box.ts +1 -1
- package/lib/synthesizers/tail.ts +2 -2
- package/lib/test-kit/corpus-recipe.ts +1 -1
- package/lib/tools/align-canonical.ts +3 -2
- package/lib/tools/audit.ts +1 -1
- package/lib/tools/corpus-stats.ts +1 -1
- package/lib/tools/fetch/download/network.ts +1 -1
- package/lib/tools/fetch/geonames/dump.ts +1 -1
- package/lib/tools/fetch/gleif.ts +2 -2
- package/lib/tools/fetch/header.ts +1 -1
- package/lib/tools/fetch/inspire-addresses.ts +1 -1
- package/lib/tools/fetch/vlaanderen-ad.ts +1 -1
- package/lib/tools/fetch/wfs-harvest.ts +6 -6
- package/lib/tools/fetch/zip-archive.ts +2 -2
- package/lib/tools/fetch.ts +2 -0
- package/lib/tools/golden/expand.ts +1 -1
- package/lib/tools/golden/promote.ts +3 -3
- package/lib/tools/golden/relabel-street/directory.ts +2 -1
- package/lib/tools/lint/recipe-output/vocab.ts +2 -2
- package/lib/tools/lint/recipe-output.ts +1 -1
- package/lib/tools/migrate/source-names.ts +1 -1
- package/lib/tools/overlay/manifest.ts +62 -10
- package/lib/tools/overlay/split-slice.ts +2 -10
- package/lib/tools/postcode-triples.ts +2 -2
- package/lib/tools/sub/venue/head-nouns.ts +4 -3
- package/lib/types.ts +3 -3
- package/lib/us/adapters/state/tx-notaries/adapter.ts +1 -1
- package/lib/us/adapters/usgov/irs-bmf/adapter.ts +2 -2
- package/lib/us/adapters/usgov/nad/adapter.ts +1 -1
- package/lib/us/adapters/usgov/nppes/adapter.ts +2 -2
- package/lib/us/synthesizers/intersection.ts +4 -4
- package/lib/us/synthesizers/street.ts +3 -3
- package/lib/us/tools/fetch/nad.ts +2 -2
- package/lib/utils/split.ts +59 -6
- package/lib/utils/wof-json.ts +1 -1
- package/out/adapters/cordis/adapter.d.ts +7 -7
- package/out/adapters/cordis/adapter.js +9 -9
- package/out/adapters/cordis/adapter.js.map +1 -1
- package/out/adapters/gleif/adapter.d.ts +7 -8
- package/out/adapters/gleif/adapter.d.ts.map +1 -1
- package/out/adapters/gleif/adapter.js +7 -8
- package/out/adapters/gleif/adapter.js.map +1 -1
- package/out/adapters/po-box/adapter.d.ts +1 -1
- package/out/adapters/source-id.d.ts +1 -1
- package/out/adapters/source-id.js +1 -1
- package/out/adapters.d.ts +2 -2
- package/out/adapters.d.ts.map +1 -1
- package/out/adapters.js +4 -2
- package/out/adapters.js.map +1 -1
- package/out/au/adapters/gnaf/adapter.js +1 -1
- package/out/be/adapters/brussels/adapter.d.ts +2 -2
- package/out/be/adapters/brussels/adapter.js +3 -3
- package/out/be/adapters/vlaanderen/adapter.d.ts +1 -1
- package/out/be/adapters/wallonie/adapter.d.ts +1 -1
- package/out/be/adapters/wallonie/adapter.js +1 -1
- package/out/build/align.d.ts +1 -1
- package/out/build.js +1 -1
- package/out/build.js.map +1 -1
- package/out/cz/adapters/cuzk/adapter.d.ts +2 -2
- package/out/cz/adapters/cuzk/adapter.js +2 -2
- package/out/cz/tools/fetch/cuzk.d.ts +2 -2
- package/out/cz/tools/fetch/cuzk.js +4 -4
- package/out/cz/tools/fetch/cuzk.js.map +1 -1
- package/out/de/recipes/locale.d.ts +1 -1
- package/out/de/recipes/locale.js +1 -1
- package/out/dk/adapters/inspire/adapter.js +1 -1
- package/out/ee/tools/fetch/ads.d.ts +2 -2
- package/out/ee/tools/fetch/ads.js +1 -1
- package/out/es/adapters/bizkaia/adapter.js +1 -1
- package/out/es/adapters/navarra/adapter.d.ts +2 -2
- package/out/es/adapters/navarra/adapter.js +2 -2
- package/out/es/cadastre.d.ts +2 -2
- package/out/es/cadastre.js +2 -2
- package/out/es/tools/fetch/bizkaia.d.ts +5 -5
- package/out/es/tools/fetch/bizkaia.js +6 -6
- package/out/es/tools/fetch/bizkaia.js.map +1 -1
- package/out/es/tools/fetch/catastro.d.ts +4 -4
- package/out/es/tools/fetch/catastro.js +2 -2
- package/out/es/tools/fetch/navarra.d.ts +2 -2
- package/out/es/tools/fetch/navarra.js +2 -2
- package/out/fingerprints.d.ts +3 -3
- package/out/fingerprints.js +3 -3
- package/out/fr/adapters/finess/adapter.d.ts +6 -5
- package/out/fr/adapters/finess/adapter.d.ts.map +1 -1
- package/out/fr/adapters/finess/adapter.js +6 -5
- package/out/fr/adapters/finess/adapter.js.map +1 -1
- package/out/fr/adapters/finess/voie-type.d.ts +1 -1
- package/out/fr/adapters/finess/voie-type.js +1 -1
- package/out/fr/tools/fetch/annuaire-education.d.ts +3 -3
- package/out/fr/tools/fetch/annuaire-education.js +3 -3
- package/out/gb/adapters/os-open/adapter.d.ts +165 -0
- package/out/gb/adapters/os-open/adapter.d.ts.map +1 -0
- package/out/gb/adapters/os-open/adapter.js +298 -0
- package/out/gb/adapters/os-open/adapter.js.map +1 -0
- package/out/gb/constituent-country.d.ts +36 -0
- package/out/gb/constituent-country.d.ts.map +1 -0
- package/out/gb/constituent-country.js +30 -0
- package/out/gb/constituent-country.js.map +1 -0
- package/out/gb/os-open/nearest-link.d.ts +73 -0
- package/out/gb/os-open/nearest-link.d.ts.map +1 -0
- package/out/gb/os-open/nearest-link.js +133 -0
- package/out/gb/os-open/nearest-link.js.map +1 -0
- package/out/gb/os-open/open-names.d.ts +92 -0
- package/out/gb/os-open/open-names.d.ts.map +1 -0
- package/out/gb/os-open/open-names.js +107 -0
- package/out/gb/os-open/open-names.js.map +1 -0
- package/out/gb/os-open/open-roads.d.ts +80 -0
- package/out/gb/os-open/open-roads.d.ts.map +1 -0
- package/out/gb/os-open/open-roads.js +79 -0
- package/out/gb/os-open/open-roads.js.map +1 -0
- package/out/gb/tools/fetch/os-open.d.ts +91 -0
- package/out/gb/tools/fetch/os-open.d.ts.map +1 -0
- package/out/gb/tools/fetch/os-open.js +166 -0
- package/out/gb/tools/fetch/os-open.js.map +1 -0
- package/out/inspire/address.d.ts +3 -3
- package/out/inspire/address.js +3 -3
- package/out/international/recipes/locale.d.ts +6 -0
- package/out/international/recipes/locale.d.ts.map +1 -1
- package/out/international/recipes/locale.js +29 -7
- package/out/international/recipes/locale.js.map +1 -1
- package/out/it/adapters/anac/adapter.d.ts +1 -1
- package/out/it/adapters/anac/adapter.d.ts.map +1 -1
- package/out/it/adapters/anac/adapter.js +4 -3
- package/out/it/adapters/anac/adapter.js.map +1 -1
- package/out/jp/adapters/wof-admin/adapter.d.ts +2 -2
- package/out/jp/adapters/wof-admin/adapter.js +2 -2
- package/out/kr/adapters/juso/label-rows.d.ts +1 -1
- package/out/kr/adapters/localdata/key-index.d.ts +2 -1
- package/out/kr/adapters/localdata/key-index.d.ts.map +1 -1
- package/out/kr/adapters/localdata/key-index.js +2 -1
- package/out/kr/adapters/localdata/key-index.js.map +1 -1
- package/out/lu/adapters/bd-adresses/adapter.d.ts +1 -1
- package/out/lu/adapters/bd-adresses/adapter.js +1 -1
- package/out/nl/adapters/kadaster/adapter.js +2 -2
- package/out/nl/tools/fetch/kadaster.d.ts +2 -2
- package/out/nl/tools/fetch/kadaster.js +2 -2
- package/out/parquet/shuffle.d.ts +2 -2
- package/out/parquet/shuffle.js +2 -2
- package/out/parquet/span-sql.d.ts +8 -6
- package/out/parquet/span-sql.d.ts.map +1 -1
- package/out/parquet/span-sql.js +8 -6
- package/out/parquet/span-sql.js.map +1 -1
- package/out/parquet/streams.d.ts +1 -1
- package/out/parquet/writers.d.ts +2 -2
- package/out/parquet/writers.js +1 -1
- package/out/pl/tools/fetch/emuia.d.ts +2 -2
- package/out/recipes/scaffold.d.ts +2 -2
- package/out/recipes/sources.d.ts +2 -2
- package/out/recipes/sources.js +3 -3
- package/out/recipes/sources.js.map +1 -1
- package/out/recipes/sub/venue/render.d.ts +1 -1
- package/out/recipes/sub/venue/render.js +1 -1
- package/out/recipes/sub/venue/sources.d.ts +4 -3
- package/out/recipes/sub/venue/sources.d.ts.map +1 -1
- package/out/recipes/sub/venue/sources.js +4 -3
- package/out/recipes/sub/venue/sources.js.map +1 -1
- package/out/recipes/sub/venue.d.ts +3 -2
- package/out/recipes/sub/venue.d.ts.map +1 -1
- package/out/recipes/sub/venue.js +2 -2
- package/out/recipes/sub/venue.js.map +1 -1
- package/out/recipes/venue.d.ts +7 -6
- package/out/recipes/venue.d.ts.map +1 -1
- package/out/recipes/venue.js +11 -10
- package/out/recipes/venue.js.map +1 -1
- package/out/registers.d.ts +7 -0
- package/out/registers.d.ts.map +1 -1
- package/out/registers.js +7 -0
- package/out/registers.js.map +1 -1
- package/out/ro/adapters/retea-scolara/adapter.d.ts +2 -2
- package/out/ro/adapters/retea-scolara/adapter.js +2 -2
- package/out/runner.d.ts +3 -3
- package/out/runner.js +2 -2
- package/out/sk/tools/fetch/inspire.d.ts +3 -3
- package/out/sk/tools/fetch/inspire.js +1 -1
- package/out/source-register/effective-manifest.d.ts +11 -5
- package/out/source-register/effective-manifest.d.ts.map +1 -1
- package/out/source-register/effective-manifest.js +9 -4
- package/out/source-register/effective-manifest.js.map +1 -1
- package/out/source-register/training-manifest.d.ts +27 -0
- package/out/source-register/training-manifest.d.ts.map +1 -1
- package/out/source-register/training-manifest.js +13 -1
- package/out/source-register/training-manifest.js.map +1 -1
- package/out/source-register/types.d.ts +2 -2
- package/out/source-register.d.ts +1 -1
- package/out/source-register.d.ts.map +1 -1
- package/out/source-register.js +1 -1
- package/out/source-register.js.map +1 -1
- package/out/subvenue/harvest.d.ts +4 -3
- package/out/subvenue/harvest.d.ts.map +1 -1
- package/out/subvenue/harvest.js +6 -5
- package/out/subvenue/harvest.js.map +1 -1
- package/out/subvenue/promotions.d.ts +2 -2
- package/out/subvenue/promotions.js +3 -3
- package/out/subvenue/promotions.js.map +1 -1
- package/out/subvenue/surfaces.d.ts +1 -1
- package/out/subvenue/table.d.ts +6 -6
- package/out/subvenue/table.js +1 -1
- package/out/surfaces/locale.d.ts +1 -1
- package/out/surfaces/locale.js +1 -1
- package/out/synthesizers/boundary-stress.d.ts.map +1 -1
- package/out/synthesizers/boundary-stress.js +2 -1
- package/out/synthesizers/boundary-stress.js.map +1 -1
- package/out/synthesizers/tail.d.ts +2 -2
- package/out/synthesizers/tail.js +2 -2
- package/out/test-kit/corpus-recipe.d.ts +1 -1
- package/out/test-kit/corpus-recipe.js +1 -1
- package/out/tools/align-canonical.d.ts.map +1 -1
- package/out/tools/align-canonical.js +3 -2
- package/out/tools/align-canonical.js.map +1 -1
- package/out/tools/audit.js +1 -1
- package/out/tools/corpus-stats.d.ts +1 -1
- package/out/tools/fetch/download/network.d.ts +1 -1
- package/out/tools/fetch/download/network.js +1 -1
- package/out/tools/fetch/geonames/dump.d.ts +1 -1
- package/out/tools/fetch/geonames/dump.js +1 -1
- package/out/tools/fetch/gleif.d.ts +2 -2
- package/out/tools/fetch/gleif.js +1 -1
- package/out/tools/fetch/header.d.ts +1 -1
- package/out/tools/fetch/header.js +1 -1
- package/out/tools/fetch/inspire-addresses.d.ts +1 -1
- package/out/tools/fetch/vlaanderen-ad.d.ts +1 -1
- package/out/tools/fetch/wfs-harvest.d.ts +3 -3
- package/out/tools/fetch/wfs-harvest.js +4 -4
- package/out/tools/fetch/wfs-harvest.js.map +1 -1
- package/out/tools/fetch/zip-archive.d.ts +2 -2
- package/out/tools/fetch/zip-archive.js +2 -2
- package/out/tools/fetch.d.ts +2 -0
- package/out/tools/fetch.d.ts.map +1 -1
- package/out/tools/fetch.js +2 -0
- package/out/tools/fetch.js.map +1 -1
- package/out/tools/golden/expand.js +1 -1
- package/out/tools/golden/expand.js.map +1 -1
- package/out/tools/golden/promote.d.ts +1 -1
- package/out/tools/golden/promote.js +3 -3
- package/out/tools/golden/promote.js.map +1 -1
- package/out/tools/golden/relabel-street/directory.d.ts +2 -1
- package/out/tools/golden/relabel-street/directory.d.ts.map +1 -1
- package/out/tools/golden/relabel-street/directory.js.map +1 -1
- package/out/tools/lint/recipe-output/vocab.js +2 -2
- package/out/tools/lint/recipe-output.d.ts +1 -1
- package/out/tools/migrate/source-names.d.ts +1 -1
- package/out/tools/overlay/manifest.d.ts +15 -2
- package/out/tools/overlay/manifest.d.ts.map +1 -1
- package/out/tools/overlay/manifest.js +41 -10
- package/out/tools/overlay/manifest.js.map +1 -1
- package/out/tools/overlay/split-slice.d.ts.map +1 -1
- package/out/tools/overlay/split-slice.js +2 -9
- package/out/tools/overlay/split-slice.js.map +1 -1
- package/out/tools/postcode-triples.d.ts +1 -1
- package/out/tools/postcode-triples.js +2 -2
- package/out/tools/postcode-triples.js.map +1 -1
- package/out/tools/sub/venue/head-nouns.d.ts +1 -1
- package/out/tools/sub/venue/head-nouns.d.ts.map +1 -1
- package/out/tools/sub/venue/head-nouns.js +4 -3
- package/out/tools/sub/venue/head-nouns.js.map +1 -1
- package/out/types.d.ts +3 -3
- package/out/types.js +1 -1
- package/out/us/adapters/state/tx-notaries/adapter.d.ts +1 -1
- package/out/us/adapters/state/tx-notaries/adapter.js +1 -1
- package/out/us/adapters/usgov/irs-bmf/adapter.d.ts +1 -1
- package/out/us/adapters/usgov/irs-bmf/adapter.js +2 -2
- package/out/us/adapters/usgov/nad/adapter.d.ts +1 -1
- package/out/us/adapters/usgov/nad/adapter.js +1 -1
- package/out/us/adapters/usgov/nppes/adapter.d.ts +1 -1
- package/out/us/adapters/usgov/nppes/adapter.js +1 -1
- package/out/us/synthesizers/intersection.js +4 -4
- package/out/us/synthesizers/intersection.js.map +1 -1
- package/out/us/synthesizers/street.js +3 -3
- package/out/us/synthesizers/street.js.map +1 -1
- package/out/us/tools/fetch/nad.d.ts +2 -2
- package/out/us/tools/fetch/nad.js +2 -2
- package/out/utils/split.d.ts +21 -0
- package/out/utils/split.d.ts.map +1 -1
- package/out/utils/split.js +49 -5
- package/out/utils/split.js.map +1 -1
- package/out/utils/wof-json.d.ts +1 -1
- package/out/utils/wof-json.js +1 -1
- package/package.json +15 -14
package/lib/subvenue/harvest.ts
CHANGED
|
@@ -71,9 +71,10 @@ export interface SubVenueHarvestRow {
|
|
|
71
71
|
/**
|
|
72
72
|
* Classify an OSM `ref` into an {@link IdentifierShape} class.
|
|
73
73
|
*
|
|
74
|
-
* The classes are the ones Berlin's gates
|
|
74
|
+
* The classes are the ones Berlin's airport gates produced, plus the two aviation forms
|
|
75
75
|
* the corpus task names (`Terminal 2F` is digit-letter, `Concourse B` is letter).
|
|
76
|
-
* `range` covers both separators OSM uses for a gate serving more
|
|
76
|
+
* `range` covers both separators OSM uses for a boarding gate serving more
|
|
77
|
+
* than one stand: `16-18` and `0/1`.
|
|
77
78
|
*/
|
|
78
79
|
export function classifyIdentifier(ref: string): string {
|
|
79
80
|
const value = ref.trim()
|
|
@@ -92,10 +93,10 @@ export function classifyIdentifier(ref: string): string {
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
/**
|
|
95
|
-
*
|
|
96
|
+
* The number of real `ref` values each {@link IdentifierShape} keeps.
|
|
96
97
|
*
|
|
97
98
|
* Eight rather than "all" and not one.
|
|
98
|
-
* The field exists so a recipe author can see what a class
|
|
99
|
+
* The field exists so a recipe author can see what a class contains.
|
|
99
100
|
*
|
|
100
101
|
* GB's `other` class turned out to be semicolon multi-values (`1.2.3`, `13.14`),
|
|
101
102
|
* which one example would have hidden and which the class name does not say.
|
|
@@ -128,7 +129,7 @@ export interface HarvestOptions {
|
|
|
128
129
|
/**
|
|
129
130
|
* Harvest attested phrases and identifier shapes out of a source's rows.
|
|
130
131
|
*
|
|
131
|
-
* `index`
|
|
132
|
+
* `index` decides whether the name harvest runs.
|
|
132
133
|
* A name contributes only when it contains a phrase already in the table.
|
|
133
134
|
*
|
|
134
135
|
* That filter is the whole reason this function is safe to run over raw OSM:
|
|
@@ -60,8 +60,8 @@ export interface SubVenuePromotion {
|
|
|
60
60
|
* This ledger is the only input that sets `curated: true` on a machine-derived surface.
|
|
61
61
|
* Rejections stay in the ledger so the system can reject duplicate proposals until new evidence arrives.
|
|
62
62
|
*
|
|
63
|
-
* The span proposer in `packages/neural/lib/venue/structure.ts` ships its English designators
|
|
64
|
-
*
|
|
63
|
+
* The span proposer in `packages/neural/lib/venue/structure.ts` ships its English designators without
|
|
64
|
+
* a locale restriction, so a rejection here guides recipes only and does not stop the proposer.
|
|
65
65
|
*/
|
|
66
66
|
export const SUBVENUE_PROMOTIONS: readonly SubVenuePromotion[] = [
|
|
67
67
|
// wing
|
|
@@ -171,7 +171,7 @@ export const SUBVENUE_PROMOTIONS: readonly SubVenuePromotion[] = [
|
|
|
171
171
|
census: "france.jsonl 2026-08-05 (251,260 rows), 40 hits; all 19 shape hits enumerated",
|
|
172
172
|
},
|
|
173
173
|
|
|
174
|
-
// gate: the English surface ships without modifier eligibility.
|
|
174
|
+
// The airport gate designator: the English surface ships without modifier eligibility.
|
|
175
175
|
// These entries cover its localized forms.
|
|
176
176
|
{
|
|
177
177
|
designatorID: "gate",
|
package/lib/subvenue/surfaces.ts
CHANGED
|
@@ -42,7 +42,7 @@ export function normalizeSurface(text: string): string {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* The normalized phrase keys this phrase-to-record index.
|
|
46
46
|
* It attributes a matched phrase to its record.
|
|
47
47
|
*/
|
|
48
48
|
export type SurfaceIndex = ReadonlyMap<string, { recordID: string; recordKind: "designator" | "modifier" }>
|
package/lib/subvenue/table.ts
CHANGED
|
@@ -104,13 +104,13 @@ export interface SubVenueSurface {
|
|
|
104
104
|
/**
|
|
105
105
|
* Whether a human has approved this surface for parsing use in its region.
|
|
106
106
|
*
|
|
107
|
-
* Machine-derived entries start `false`; only a matching {@link SubVenuePromotion}
|
|
108
|
-
*
|
|
107
|
+
* Machine-derived entries start `false`; only a matching {@link SubVenuePromotion} flips it,
|
|
108
|
+
* so a consumer that accepts or refuses a parse by this table must filter on this.
|
|
109
109
|
*/
|
|
110
110
|
curated: boolean
|
|
111
111
|
/**
|
|
112
|
-
*
|
|
113
|
-
* Vocabulary sources attest phrase existence and use a count of `0`.
|
|
112
|
+
* The number of source features that attested this exact phrase when the source counts
|
|
113
|
+
* (OSM, Overture); Vocabulary sources attest phrase existence and use a count of `0`.
|
|
114
114
|
* OSM and Overture sources count occurrences.
|
|
115
115
|
*/
|
|
116
116
|
observations: number
|
|
@@ -138,7 +138,7 @@ export interface IdentifierShape {
|
|
|
138
138
|
/**
|
|
139
139
|
* ISO 3166-1 alpha-2 of the extract this distribution was measured in.
|
|
140
140
|
*
|
|
141
|
-
* It is per-region because the shapes differ (GB gates are 70% bare digits, Japanese platform
|
|
141
|
+
* It is per-region because the shapes differ (GB airport gates are 70% bare digits, Japanese platform
|
|
142
142
|
* refs a different range), so a recipe for a French address should sample France's distribution.
|
|
143
143
|
*/
|
|
144
144
|
region: string
|
|
@@ -190,7 +190,7 @@ export interface SubVenueLexiconTable {
|
|
|
190
190
|
* below for the module docstring's dependency-direction reason.
|
|
191
191
|
*
|
|
192
192
|
* `tier` is added here: the seven WOF placetypes plus `terminal`/`gate` are all venue-interior,
|
|
193
|
-
* while `campus` and `building` name a whole venue as
|
|
193
|
+
* while `campus` and `building` name a whole venue about as frequently as a part of one
|
|
194
194
|
* but are marked `subvenue` because that is the role the span proposer uses them in.
|
|
195
195
|
*/
|
|
196
196
|
export const SHIPPED_DESIGNATOR_SEED: ReadonlyArray<{
|
package/lib/surfaces/locale.ts
CHANGED
|
@@ -156,7 +156,7 @@ function tokenPresent(raw: string, value: string): boolean {
|
|
|
156
156
|
* Render one tuple into a locale-ordered `{raw, components}` row via OpenCage templates,
|
|
157
157
|
* with light variation (house number and postcode may be dropped).
|
|
158
158
|
*
|
|
159
|
-
* Returns `null` when the tuple is too thin or a component would not align
|
|
159
|
+
* Returns `null` when the tuple is too thin or a component would not align to an exact span.
|
|
160
160
|
*
|
|
161
161
|
* Region handling depends on order:
|
|
162
162
|
* - native omits region for alignment reliability
|
|
@@ -16,7 +16,7 @@ import { sample } from "@mailwoman/core/random"
|
|
|
16
16
|
/* oxlint-disable sister-software/no-unnamed-threshold -- the bare decimals below are weighted-sampler
|
|
17
17
|
cutoffs rather than thresholds: `const r = random()` followed by a cascade of `r < 0.4` branches defines the
|
|
18
18
|
output distribution. The cascade shows each weight from top to bottom. A separate constant for each cutoff
|
|
19
|
-
would hide the distribution behind a wall of identifiers.
|
|
19
|
+
would hide the distribution behind a wall of identifiers. Decision thresholds in these files are
|
|
20
20
|
extracted as constants above. */
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -20,7 +20,7 @@ import type { CanonicalRow } from "#types"
|
|
|
20
20
|
/* oxlint-disable sister-software/no-unnamed-threshold -- the bare decimals below are weighted-sampler
|
|
21
21
|
cutoffs rather than thresholds: `const r = random()` followed by a cascade of `r < 0.4` branches is the
|
|
22
22
|
output distribution. The cascade shows each weight from top to bottom. A separate constant for each cutoff
|
|
23
|
-
would hide the distribution behind identifiers. The
|
|
23
|
+
would hide the distribution behind identifiers. The decision thresholds in these files are
|
|
24
24
|
extracted as constants above. */
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -348,7 +348,8 @@ export function synthesizeBoundaryStressRow(
|
|
|
348
348
|
|
|
349
349
|
// The layout renders the tail in the country's order: `75005 Paris` for FR
|
|
350
350
|
// and `Boston, MA 02116` for the US.
|
|
351
|
-
//
|
|
351
|
+
// The synthesizer drops the layout's commas.
|
|
352
|
+
// That is a surface perturbation that applies to any country.
|
|
352
353
|
const tail = layoutAdminTail(b.country, {
|
|
353
354
|
locality: b.locality,
|
|
354
355
|
region: b.region,
|
|
@@ -21,7 +21,7 @@ import type { CanonicalRow } from "#types"
|
|
|
21
21
|
/* oxlint-disable sister-software/no-unnamed-threshold -- the bare decimals below are weighted-sampler
|
|
22
22
|
cutoffs rather than thresholds: `const r = random()` followed by a cascade of `r < 0.4` branches defines the
|
|
23
23
|
output distribution. The cascade shows each weight from top to bottom. A separate constant for each cutoff
|
|
24
|
-
would hide the distribution behind a wall of identifiers.
|
|
24
|
+
would hide the distribution behind a wall of identifiers. Decision thresholds in these files are
|
|
25
25
|
extracted as constants above. */
|
|
26
26
|
|
|
27
27
|
export interface NoStreetBaseTuple {
|
|
@@ -21,7 +21,7 @@ const MIN_DIGITS_FOR_HYPHEN_GROUPING = 3
|
|
|
21
21
|
/* oxlint-disable sister-software/no-unnamed-threshold -- the bare decimals below are weighted-sampler
|
|
22
22
|
cutoffs rather than thresholds. `const r = random()` followed by `r < 0.4` branches defines the
|
|
23
23
|
output distribution. The branches show each weight from top to bottom. A separate constant for each cutoff
|
|
24
|
-
would hide the distribution behind identifiers.
|
|
24
|
+
would hide the distribution behind identifiers. Decision thresholds in these files are
|
|
25
25
|
constants defined above. */
|
|
26
26
|
|
|
27
27
|
/**
|
package/lib/synthesizers/tail.ts
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* synthesizer writes `Chicago, IL 60613`, `75005 Paris`, `London, EC3N 1DE` or
|
|
8
8
|
* `Maracaibo 4001, Zulia` from one call rather than from a template per country.
|
|
9
9
|
*
|
|
10
|
-
* The layout decides which parts print: the FR layout prints no region, so a FR tail
|
|
10
|
+
* The layout decides which parts print: the FR layout prints no region, so a FR tail holds none
|
|
11
11
|
* and the returned components say so. The lines the layout writes are joined with the country's
|
|
12
|
-
* line join
|
|
12
|
+
* line join. The result is the one-line form the corpus rows take.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { formatAddressRow } from "@mailwoman/codex/address/format"
|
|
@@ -70,7 +70,7 @@ export async function scratch(prefix: string, tuples: object[], surfaces: string
|
|
|
70
70
|
export const TEST_REGISTER = "test-harness"
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
* Bind a recipe and its seed to a runner the tests call with
|
|
73
|
+
* Bind a recipe and its seed to a runner the tests call with only the tuples and reserved surfaces.
|
|
74
74
|
*
|
|
75
75
|
* The seed is required because these suites assert on generated distributions.
|
|
76
76
|
*/
|
|
@@ -7,8 +7,9 @@ import { createNewlineWriter, JSONSpliterator } from "spliterator"
|
|
|
7
7
|
*
|
|
8
8
|
* Most synthetic recipe outputs are generated on demand by a recipe (parametrized by --count),
|
|
9
9
|
* so re-emitting them in a new label format is a re-run.
|
|
10
|
-
* A few are fixed corpora with a hand/DeepSeek-authored canonical source that is never regenerated
|
|
11
|
-
*
|
|
10
|
+
* A few are fixed corpora with a hand/DeepSeek-authored canonical source that is never regenerated.
|
|
11
|
+
*
|
|
12
|
+
* They include `deepseek-kryptonite` (the adversarial hard-case set) and the `deepseek-translit-*` variants.
|
|
12
13
|
*
|
|
13
14
|
* Their committed parquets use the label format that was current when they were first built.
|
|
14
15
|
*
|
package/lib/tools/audit.ts
CHANGED
|
@@ -130,7 +130,7 @@ async function scanParquetFiles(corpusDir: PathBuilderLike, sampleCount: number)
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
function inferSourceFromFilename(filename: string): string {
|
|
133
|
-
//
|
|
133
|
+
// Some corpus builds write part-<source>-<n>.parquet or part-<n>.parquet.
|
|
134
134
|
// The latter (current build at corpus-v0.3.0) gives no source signal in the filename.
|
|
135
135
|
// See manifestScan() for the authoritative path.
|
|
136
136
|
// Return "<unknown>" so the caller flags this case.
|
|
@@ -82,7 +82,7 @@ export interface SourceManifest {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
|
-
* A status
|
|
85
|
+
* A status the download retries: rate limiting or a server-side failure.
|
|
86
86
|
*/
|
|
87
87
|
/**
|
|
88
88
|
* An HTTP failure that includes its status, so callers branch on `error.status`
|
|
@@ -116,7 +116,7 @@ const GAZETTEER_DUMP_COLUMNS = 19
|
|
|
116
116
|
* The capitals builder already holds each country dump as a string.
|
|
117
117
|
*
|
|
118
118
|
* A byte-oriented spliterator would UTF-8 encode that input and allocate up to
|
|
119
|
-
* another 350 MB
|
|
119
|
+
* another 350 MB only to inspect the first non-empty line.
|
|
120
120
|
*/
|
|
121
121
|
export function looksLikeGazetteerDump(text: string): boolean {
|
|
122
122
|
let start = 0
|
package/lib/tools/fetch/gleif.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* 1. **The API's `size` is the archive's length.** It stated 507,006,221 and the host answered a
|
|
16
16
|
* `HEAD` with `content-length` 507,006,221 and a one-byte range with `Content-Range: bytes
|
|
17
|
-
* 0-9/507006221`. The transfer is checked against the API's figure, so a body
|
|
17
|
+
* 0-9/507006221`. The transfer is checked against the API's figure, so a truncated body or a
|
|
18
18
|
* publish replaced mid-transfer is refused rather than recorded.
|
|
19
19
|
* 2. **The host honors `Range`.** An interrupted transfer resumes through
|
|
20
20
|
* {@linkcode resumableDownload}. The request names `accept-encoding: identity`, because the host
|
|
@@ -79,7 +79,7 @@ export interface GLEIFPublishedFile {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
|
-
* The receipt
|
|
82
|
+
* The receipt that sits beside the archive.
|
|
83
83
|
*/
|
|
84
84
|
export interface GLEIFGoldenCopyReceipt {
|
|
85
85
|
source: string
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* This module reads a delimited file's header line and refuses one that drops a column an adapter
|
|
7
7
|
* indexes.
|
|
8
8
|
*
|
|
9
|
-
* A fetch module checks the file it
|
|
9
|
+
* A fetch module checks the file it has written against the columns its adapter reads by name,
|
|
10
10
|
* because a renamed column reaches the adapter as an empty string on every row rather than as an
|
|
11
11
|
* error. The check belongs here rather than in each publisher's module: every caller needs the same
|
|
12
12
|
* two steps, and each one that wrote them again would also be a second answer to how the file is
|
|
@@ -131,7 +131,7 @@ export interface WFSCapabilities {
|
|
|
131
131
|
/**
|
|
132
132
|
* A value a GeoServer JSON response uses for a voidable property that holds no value.
|
|
133
133
|
*
|
|
134
|
-
* INSPIRE marks
|
|
134
|
+
* The INSPIRE schema marks a set of attributes voidable.
|
|
135
135
|
* A voidable property must be present with either a value or a void with a reason.
|
|
136
136
|
*
|
|
137
137
|
* GeoServer encodes that void as an object rather than as `null`, so `String(value)`
|
|
@@ -146,7 +146,7 @@ export interface HarvestVlaanderenOptions {
|
|
|
146
146
|
*/
|
|
147
147
|
outputDir: PathBuilderLike
|
|
148
148
|
/**
|
|
149
|
-
* Stop after this
|
|
149
|
+
* Stop after this number of address pages, for a probe rather than a full harvest.
|
|
150
150
|
*/
|
|
151
151
|
maxPages?: number
|
|
152
152
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
* The paging, manifest and resumption
|
|
6
|
+
* The paging, manifest and resumption code that every paged WFS harvest shares.
|
|
7
7
|
*
|
|
8
8
|
* `./inspire-addresses.ts` owns what an INSPIRE Addresses service exposes — its capabilities, its
|
|
9
9
|
* feature-type names and its GeoJSON pages. This module owns what a harvest of any paged WFS does
|
|
@@ -75,7 +75,7 @@ export interface MarkupRoot {
|
|
|
75
75
|
*/
|
|
76
76
|
attributes: string
|
|
77
77
|
/**
|
|
78
|
-
* The offset
|
|
78
|
+
* The offset of the first character after the opening tag.
|
|
79
79
|
*/
|
|
80
80
|
contentStart: number
|
|
81
81
|
}
|
|
@@ -158,7 +158,7 @@ export function rootContent(body: string, root: MarkupRoot, context: string): st
|
|
|
158
158
|
/**
|
|
159
159
|
* The attributes a page states about itself rather than about the feature type.
|
|
160
160
|
*
|
|
161
|
-
* A harvest assembles
|
|
161
|
+
* A harvest assembles several pages under one root element, so the first page's counts
|
|
162
162
|
* and timestamp would describe the assembled file wrongly.
|
|
163
163
|
* They are dropped and the manifest records them per page.
|
|
164
164
|
*/
|
|
@@ -420,7 +420,7 @@ export interface PagedWFSHarvestOptions {
|
|
|
420
420
|
featureCount: FeatureCountStatement
|
|
421
421
|
pageSize: number
|
|
422
422
|
/**
|
|
423
|
-
* Stop once the manifest holds this
|
|
423
|
+
* Stop once the manifest holds this number of pages, for a probe rather than a full harvest.
|
|
424
424
|
*
|
|
425
425
|
* A cap on the manifest rather than on the run, so a second run under the same cap makes no request.
|
|
426
426
|
*/
|
|
@@ -437,7 +437,7 @@ export interface PagedWFSHarvestOptions {
|
|
|
437
437
|
* Does a recorded manifest describe the request being made now?
|
|
438
438
|
*
|
|
439
439
|
* A harvest taken at another page size, ordering, format or type cannot be continued:
|
|
440
|
-
* its pages were
|
|
440
|
+
* its pages were split at different boundaries, and appending to them would leave
|
|
441
441
|
* a file whose manifest describes neither half.
|
|
442
442
|
*/
|
|
443
443
|
function describesSameRequest(manifest: WFSHarvestManifest, options: PagedWFSHarvestOptions): boolean {
|
|
@@ -932,7 +932,7 @@ export async function runWFSHarvest(
|
|
|
932
932
|
if (options.client) {
|
|
933
933
|
manifest = await options.harvest(options.client)
|
|
934
934
|
} else {
|
|
935
|
-
// Bounded retry, because a harvest is
|
|
935
|
+
// Bounded retry, because a harvest is a long series of requests and one 5xx would otherwise end the run.
|
|
936
936
|
await using client = new APIClient({
|
|
937
937
|
displayName: options.displayName,
|
|
938
938
|
minRequestIntervalMs: options.minRequestIntervalMs,
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
* @file Downloads one zip archive through an {@linkcode APIClient} and answers what arrived.
|
|
6
6
|
*
|
|
7
|
-
* An INSPIRE ATOM service that publishes one archive per area is harvested through
|
|
8
|
-
*
|
|
7
|
+
* An INSPIRE ATOM service that publishes one archive per area is harvested through one small
|
|
8
|
+
* request per area rather than through one large transfer, so the transfer runs on the client the harvest
|
|
9
9
|
* already paces and a test can drive it over a stubbed transport. `downloadToFile` runs on global
|
|
10
10
|
* `fetch`, which a unit test cannot intercept.
|
|
11
11
|
*
|
package/lib/tools/fetch.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { fetchRyhti } from "#fi/tools/fetch/ryhti"
|
|
|
19
19
|
import { fetchAnnuaireEducationOverseas } from "#fr/tools/fetch/annuaire-education"
|
|
20
20
|
import { fetchBan } from "#fr/tools/fetch/ban"
|
|
21
21
|
import { fetchFinessOverseas } from "#fr/tools/fetch/finess"
|
|
22
|
+
import { fetchGBOSOpen } from "#gb/tools/fetch/os-open"
|
|
22
23
|
import { fetchITANAC } from "#it/tools/fetch/anac"
|
|
23
24
|
import { fetchHoujinJP } from "#jp/tools/fetch/houjin"
|
|
24
25
|
import { fetchJusoKR } from "#kr/tools/fetch/juso"
|
|
@@ -67,6 +68,7 @@ export const FETCH_SOURCES = {
|
|
|
67
68
|
"es-navarra": fetchESNavarra,
|
|
68
69
|
"fr-annuaire-education-overseas": fetchAnnuaireEducationOverseas,
|
|
69
70
|
"fr-finess-overseas": fetchFinessOverseas,
|
|
71
|
+
"gb-os-open": fetchGBOSOpen,
|
|
70
72
|
"gcis-tw": fetchGCISTW,
|
|
71
73
|
gleif: fetchGLEIF,
|
|
72
74
|
"houjin-jp": fetchHoujinJP,
|
|
@@ -231,7 +231,7 @@ async function loadSeeds(
|
|
|
231
231
|
|
|
232
232
|
// Stratified sampling: read all rows from all parquet files, group by source.
|
|
233
233
|
// Bounded by per-source reservoir: keep at most max(2*count, 5000) rows per source
|
|
234
|
-
// so we don't blow memory on train parquet files (1M rows
|
|
234
|
+
// so we don't blow memory on train parquet files (1M rows per file, across every file).
|
|
235
235
|
// Later samples are uniform within each pool.
|
|
236
236
|
const bySource = new Map<string, Seed[]>()
|
|
237
237
|
const PER_SOURCE_CAP = Math.max(2 * count, 5000)
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 3. Applies filters that drop candidates unlikely to be human-typed:
|
|
14
14
|
*
|
|
15
15
|
* - Components-glued-without-commas (5+ components but <2 separators → freeform jumble)
|
|
16
|
-
* - Postcode-at-start with
|
|
16
|
+
* - Postcode-at-start with several other components (US/UK conventions put postcode last. FR puts it
|
|
17
17
|
* before locality only)
|
|
18
18
|
* - Suspicious-token signals (unmatched brackets, control chars, etc.)
|
|
19
19
|
* 4. Dedupes by normalized raw (case-insensitive, whitespace-collapsed)
|
|
@@ -47,7 +47,7 @@ import type { GoldenCandidateEntry as GoldenEntry } from "#utils/golden"
|
|
|
47
47
|
// ── Types ──────────────────────────────────────────────────────────────────
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* Components a candidate needs before it
|
|
50
|
+
* Components a candidate needs before it qualifies for a golden-set slot.
|
|
51
51
|
*/
|
|
52
52
|
const MIN_GOLDEN_COMPONENTS = 5
|
|
53
53
|
|
|
@@ -153,7 +153,7 @@ function isSuspicious(entry: GoldenEntry): boolean {
|
|
|
153
153
|
|
|
154
154
|
if (raw.split('"').length > MAX_QUOTE_SEGMENTS) return true
|
|
155
155
|
|
|
156
|
-
//
|
|
156
|
+
// more quote marks than MAX_QUOTE_SEGMENTS admits
|
|
157
157
|
return false
|
|
158
158
|
}
|
|
159
159
|
|
|
@@ -36,7 +36,8 @@ import {
|
|
|
36
36
|
export type GoldenRelabelCounts = Record<GoldenRelabelClass, number>
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* One line of the review deck: what a changed
|
|
39
|
+
* One line of the review deck: what a changed row, or an unchanged row the deck
|
|
40
|
+
* lists for review, looked like before and after.
|
|
40
41
|
*/
|
|
41
42
|
export interface GoldenRelabelDeckEntry {
|
|
42
43
|
file: string
|
|
@@ -47,7 +47,7 @@ function stripBIO(label: string): string {
|
|
|
47
47
|
*
|
|
48
48
|
* Pure-numeric tokens (house_number and postcode) are context-determined
|
|
49
49
|
* rather than lexical vocab, so they are excluded.
|
|
50
|
-
* `\p{Nd}` covers the decimal digits these address corpora
|
|
50
|
+
* `\p{Nd}` covers the decimal digits these address corpora contain.
|
|
51
51
|
*/
|
|
52
52
|
function isDigit(token: string): boolean {
|
|
53
53
|
return token.length > 0 && /^\p{Nd}+$/u.test(token)
|
|
@@ -148,7 +148,7 @@ async function readRows(con: DuckDBConnection, path: string): Promise<CorpusRow[
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
/**
|
|
151
|
-
* Read
|
|
151
|
+
* Read only the first row's `source` value, used to group base parts for a proportional sample.
|
|
152
152
|
*/
|
|
153
153
|
async function readSource(con: DuckDBConnection, path: string): Promise<string> {
|
|
154
154
|
const result = await con.runAndReadAll(`SELECT source FROM read_parquet('${path}') LIMIT 1`)
|
|
@@ -36,7 +36,7 @@ export interface SourceNameRewrite {
|
|
|
36
36
|
parquet: string
|
|
37
37
|
rows: number
|
|
38
38
|
/**
|
|
39
|
-
* The
|
|
39
|
+
* The migration applied this mapping, keyed by the retired spelling.
|
|
40
40
|
*
|
|
41
41
|
* A file whose rows already use current spellings is reported with an empty map and left untouched.
|
|
42
42
|
*/
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
* Assembles a corpus manifest
|
|
6
|
+
* Assembles a corpus manifest from a base corpus's files and new parquet files.
|
|
7
|
+
* A replaced source's base files are dropped.
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import { dataRootPath } from "@mailwoman/core/data-root"
|
|
@@ -203,6 +204,10 @@ export interface OverlayPlan {
|
|
|
203
204
|
* The filename was the only place that showed this (#2359).
|
|
204
205
|
*/
|
|
205
206
|
files: Array<{ parquet: string; source: string; split: SplitName; route: SplitRoute }>
|
|
207
|
+
/**
|
|
208
|
+
* The base sources whose files this overlay dropped.
|
|
209
|
+
*/
|
|
210
|
+
replacedSources: string[]
|
|
206
211
|
}
|
|
207
212
|
|
|
208
213
|
/**
|
|
@@ -240,6 +245,12 @@ export interface OverlayManifestOptions {
|
|
|
240
245
|
*/
|
|
241
246
|
files: readonly OverlayFile[]
|
|
242
247
|
note: string
|
|
248
|
+
/**
|
|
249
|
+
* Base sources whose files the overlay drops, so the added files take their place.
|
|
250
|
+
*
|
|
251
|
+
* Each source in this list must appear in the base, and its rows leave the split counts.
|
|
252
|
+
*/
|
|
253
|
+
replaceSources?: readonly string[]
|
|
243
254
|
}
|
|
244
255
|
|
|
245
256
|
/**
|
|
@@ -269,7 +280,9 @@ export function localManifestFilePath(path: string): string {
|
|
|
269
280
|
}
|
|
270
281
|
|
|
271
282
|
/**
|
|
272
|
-
* Writes a corpus manifest that keeps
|
|
283
|
+
* Writes a corpus manifest that keeps the files of `args.base` and appends `args.files`.
|
|
284
|
+
*
|
|
285
|
+
* A base file whose source `args.replaceSources` lists is dropped.
|
|
273
286
|
*
|
|
274
287
|
* A `val` or `test` file must use the `.<split>.parquet` suffix written by `splitOverlaySlice`.
|
|
275
288
|
* The suffix shows that the holdout policy chose its rows.
|
|
@@ -291,8 +304,16 @@ export async function assembleOverlayManifest(args: OverlayManifestOptions): Pro
|
|
|
291
304
|
)
|
|
292
305
|
}
|
|
293
306
|
|
|
307
|
+
const replaced = new Set(args.replaceSources)
|
|
308
|
+
|
|
309
|
+
for (const source of replaced) {
|
|
310
|
+
if (!baseFiles.some((s) => s.source === source)) {
|
|
311
|
+
throw new Error(`${args.base} holds no file with source '${source}', so there is nothing for it to replace.`)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
294
315
|
for (const file of args.files) {
|
|
295
|
-
if (baseFiles.some((s) => s.source === file.source)) {
|
|
316
|
+
if (!replaced.has(file.source) && baseFiles.some((s) => s.source === file.source)) {
|
|
296
317
|
console.log(`WARN: base already contains source '${file.source}' — is this the right base?`)
|
|
297
318
|
}
|
|
298
319
|
}
|
|
@@ -318,7 +339,24 @@ export async function assembleOverlayManifest(args: OverlayManifestOptions): Pro
|
|
|
318
339
|
)
|
|
319
340
|
}
|
|
320
341
|
|
|
321
|
-
const
|
|
342
|
+
const dropped = baseFiles.filter((s) => s.source !== undefined && replaced.has(s.source))
|
|
343
|
+
const droppedRows: Record<SplitName, number> = { train: 0, val: 0, test: 0 }
|
|
344
|
+
|
|
345
|
+
for (const file of dropped) {
|
|
346
|
+
const split = file["split"] as SplitName
|
|
347
|
+
const rows = file["rows"]
|
|
348
|
+
|
|
349
|
+
if (typeof rows !== "number" || !(split in droppedRows)) {
|
|
350
|
+
throw new Error(`${file.path} records no row count or split, so dropping it would leave the counts unknown.`)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
droppedRows[split] += rows
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const kept = baseFiles
|
|
357
|
+
.filter((s) => !dropped.includes(s))
|
|
358
|
+
.map((s) => ({ ...s, path: rerootBaseFilePath(s.path, args.base) }))
|
|
359
|
+
|
|
322
360
|
const added: ParquetFileDescriptor[] = []
|
|
323
361
|
|
|
324
362
|
const newDir = PathBuilder.from(args.newDir)
|
|
@@ -345,20 +383,31 @@ export async function assembleOverlayManifest(args: OverlayManifestOptions): Pro
|
|
|
345
383
|
|
|
346
384
|
const sources = args.files.map((file) => file.source).join(", ")
|
|
347
385
|
|
|
386
|
+
const defaultNote = replaced.size
|
|
387
|
+
? `${base.corpus_version} files without ${[...replaced].join(", ")} + ${sources}.`
|
|
388
|
+
: `${base.corpus_version} files (all kept verbatim) + ${sources}. Pure overlay add.`
|
|
389
|
+
|
|
348
390
|
const manifest = {
|
|
349
391
|
corpus_version: args.version,
|
|
350
392
|
overlay_base: base.corpus_version ?? null,
|
|
351
|
-
note: args.note ||
|
|
393
|
+
note: args.note || defaultNote,
|
|
352
394
|
schema: base.schema,
|
|
353
395
|
rows_per_slice: baseRowsPerFile(base),
|
|
354
396
|
row_group_size: base.row_group_size,
|
|
355
397
|
slices: [...kept, ...added],
|
|
356
398
|
counts: {
|
|
357
|
-
train: base.counts.train + addedRows.train,
|
|
358
|
-
val: base.counts.val + addedRows.val,
|
|
359
|
-
test: base.counts.test + addedRows.test,
|
|
399
|
+
train: base.counts.train - droppedRows.train + addedRows.train,
|
|
400
|
+
val: base.counts.val - droppedRows.val + addedRows.val,
|
|
401
|
+
test: base.counts.test - droppedRows.test + addedRows.test,
|
|
360
402
|
},
|
|
361
|
-
total_rows:
|
|
403
|
+
total_rows:
|
|
404
|
+
base.total_rows -
|
|
405
|
+
droppedRows.train -
|
|
406
|
+
droppedRows.val -
|
|
407
|
+
droppedRows.test +
|
|
408
|
+
addedRows.train +
|
|
409
|
+
addedRows.val +
|
|
410
|
+
addedRows.test,
|
|
362
411
|
// An overlay corpus's manifest reads no row's `license` column, so it states no license set.
|
|
363
412
|
// This value in the artifact prevents a reader from deriving an attribution table
|
|
364
413
|
// from `slices` and treating the base build's set as the whole.
|
|
@@ -389,6 +438,7 @@ export async function assembleOverlayManifest(args: OverlayManifestOptions): Pro
|
|
|
389
438
|
split: file.split ?? "train",
|
|
390
439
|
route: splitRouteFor(file.parquet),
|
|
391
440
|
})),
|
|
441
|
+
replacedSources: [...replaced],
|
|
392
442
|
}
|
|
393
443
|
|
|
394
444
|
const planPath = newDir(OVERLAY_PLAN_FILE)
|
|
@@ -397,7 +447,9 @@ export async function assembleOverlayManifest(args: OverlayManifestOptions): Pro
|
|
|
397
447
|
|
|
398
448
|
console.log(`wrote ${planPath}`)
|
|
399
449
|
console.log(`wrote ${out}`)
|
|
400
|
-
console.log(
|
|
450
|
+
console.log(
|
|
451
|
+
` files: ${manifest.slices.length} (${kept.length} base kept, ${dropped.length} base dropped, +${added.length} added)`
|
|
452
|
+
)
|
|
401
453
|
console.log(` counts: ${stringifyJSON(manifest.counts)} total: ${manifest.total_rows}`)
|
|
402
454
|
|
|
403
455
|
// The route prints beside the split, because a hand-placed split is otherwise visible only in a filename.
|
|
@@ -15,15 +15,7 @@ import type { ParquetRow } from "#parquet/schema"
|
|
|
15
15
|
import { openParquetRowStream } from "#parquet/streams"
|
|
16
16
|
import { writeParquetFile } from "#parquet/writers"
|
|
17
17
|
import type { CanonicalRow } from "#types"
|
|
18
|
-
import { type CountryHoldout, defaultHoldouts, type SplitName, splitForRow } from "#utils/split"
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The component tags the holdout policy reads.
|
|
22
|
-
*
|
|
23
|
-
* `splitForRow` consults `region`, `postcode` and `locality` and no other field,
|
|
24
|
-
* so reconstructing the rest would cost a string slice per span for no decision.
|
|
25
|
-
*/
|
|
26
|
-
const HOLDOUT_TAGS = new Set<string>(["region", "postcode", "locality"])
|
|
18
|
+
import { type CountryHoldout, defaultHoldouts, HOLDOUT_COMPONENT_TAGS, type SplitName, splitForRow } from "#utils/split"
|
|
27
19
|
|
|
28
20
|
/**
|
|
29
21
|
* The fields {@linkcode holdoutComponents} reads, with the span triple optional
|
|
@@ -63,7 +55,7 @@ export function holdoutComponents(row: SpannedRow, index: number, input: string)
|
|
|
63
55
|
const components: Record<string, string> = {}
|
|
64
56
|
|
|
65
57
|
for (const [span, tag] of tags.entries()) {
|
|
66
|
-
if (!
|
|
58
|
+
if (!HOLDOUT_COMPONENT_TAGS.has(tag) || components[tag]) continue
|
|
67
59
|
|
|
68
60
|
components[tag] = raw.slice(starts[span]!, ends[span]!)
|
|
69
61
|
}
|