@mailwoman/corpus 8.6.0 → 9.1.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 +2 -2
- package/data/PROVENANCE.md +214 -0
- package/data/sub-venue-lexicon.json +18269 -0
- package/out/src/adapters/ban/adapter.d.ts +5 -4
- package/out/src/adapters/ban/adapter.d.ts.map +1 -1
- package/out/src/adapters/ban/adapter.js +62 -69
- package/out/src/adapters/ban/adapter.js.map +1 -1
- package/out/src/adapters/ban/street-decompose.d.ts.map +1 -1
- package/out/src/adapters/ban/street-decompose.js +18 -25
- package/out/src/adapters/ban/street-decompose.js.map +1 -1
- package/out/src/adapters/fcc-bdc/adapter.d.ts +1 -7
- package/out/src/adapters/fcc-bdc/adapter.d.ts.map +1 -1
- package/out/src/adapters/fcc-bdc/adapter.js +4 -26
- package/out/src/adapters/fcc-bdc/adapter.js.map +1 -1
- package/out/src/adapters/geonames/adapter.d.ts +1 -1
- package/out/src/adapters/geonames/adapter.d.ts.map +1 -1
- package/out/src/adapters/geonames/adapter.js +72 -78
- package/out/src/adapters/geonames/adapter.js.map +1 -1
- package/out/src/adapters/geonames-postal/adapter.d.ts +1 -1
- package/out/src/adapters/geonames-postal/adapter.d.ts.map +1 -1
- package/out/src/adapters/geonames-postal/adapter.js +46 -51
- package/out/src/adapters/geonames-postal/adapter.js.map +1 -1
- package/out/src/adapters/gnaf/adapter.d.ts +1 -1
- package/out/src/adapters/gnaf/adapter.d.ts.map +1 -1
- package/out/src/adapters/gnaf/adapter.js +6 -9
- package/out/src/adapters/gnaf/adapter.js.map +1 -1
- package/out/src/adapters/gnaf/assemble.d.ts.map +1 -1
- package/out/src/adapters/gnaf/assemble.js +7 -12
- package/out/src/adapters/gnaf/assemble.js.map +1 -1
- package/out/src/adapters/index.d.ts +1 -1
- package/out/src/adapters/index.d.ts.map +1 -1
- package/out/src/adapters/index.js +1 -1
- package/out/src/adapters/index.js.map +1 -1
- package/out/src/adapters/openaddresses/adapter.d.ts +1 -1
- package/out/src/adapters/openaddresses/adapter.d.ts.map +1 -1
- package/out/src/adapters/openaddresses/adapter.js +5 -10
- package/out/src/adapters/openaddresses/adapter.js.map +1 -1
- package/out/src/adapters/overture/adapter.d.ts +1 -1
- package/out/src/adapters/overture/adapter.d.ts.map +1 -1
- package/out/src/adapters/overture/adapter.js +5 -9
- package/out/src/adapters/overture/adapter.js.map +1 -1
- package/out/src/adapters/state-hi-schools/adapter.d.ts +1 -1
- package/out/src/adapters/state-hi-schools/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-hi-schools/adapter.js +57 -75
- package/out/src/adapters/state-hi-schools/adapter.js.map +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.d.ts +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.js +60 -78
- package/out/src/adapters/state-ia-contractors/adapter.js.map +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.d.ts +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.js +69 -87
- package/out/src/adapters/state-ny-notaries/adapter.js.map +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.d.ts +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.d.ts.map +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.js +71 -89
- package/out/src/adapters/state-tx-notaries/adapter.js.map +1 -1
- package/out/src/adapters/synth-po-box/adapter.d.ts +3 -3
- package/out/src/adapters/synth-po-box/adapter.d.ts.map +1 -1
- package/out/src/adapters/synth-po-box/adapter.js +10 -18
- package/out/src/adapters/synth-po-box/adapter.js.map +1 -1
- package/out/src/adapters/tiger/adapter.d.ts +1 -1
- package/out/src/adapters/tiger/adapter.d.ts.map +1 -1
- package/out/src/adapters/tiger/adapter.js +2 -2
- package/out/src/adapters/tiger/adapter.js.map +1 -1
- package/out/src/adapters/tiger/street-decompose.d.ts.map +1 -1
- package/out/src/adapters/tiger/street-decompose.js +18 -27
- package/out/src/adapters/tiger/street-decompose.js.map +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +4 -4
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.js +64 -82
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.js.map +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.js +62 -84
- package/out/src/adapters/usgov-imls-pls/adapter.js.map +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.js +59 -66
- package/out/src/adapters/usgov-irs-bmf/adapter.js.map +1 -1
- package/out/src/adapters/usgov-nad/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-nad/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-nad/adapter.js +6 -9
- package/out/src/adapters/usgov-nad/adapter.js.map +1 -1
- package/out/src/adapters/usgov-nppes/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-nppes/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-nppes/adapter.js +60 -78
- package/out/src/adapters/usgov-nppes/adapter.js.map +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts.map +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js +53 -73
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js.map +1 -1
- package/out/src/{adapter.d.ts → adapters/utils/index.d.ts} +43 -2
- package/out/src/adapters/utils/index.d.ts.map +1 -0
- package/out/src/{adapter.js → adapters/utils/index.js} +47 -2
- package/out/src/adapters/utils/index.js.map +1 -0
- package/out/src/adapters/wof-admin-jp/adapter.d.ts +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.js +24 -6
- package/out/src/adapters/wof-admin-jp/adapter.js.map +1 -1
- package/out/src/adapters/wof-admin-json/adapter.d.ts +2 -2
- package/out/src/adapters/wof-admin-json/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-admin-json/adapter.js +2 -2
- package/out/src/adapters/wof-admin-json/adapter.js.map +1 -1
- package/out/src/adapters/wof-postalcode-json/adapter.d.ts +2 -2
- package/out/src/adapters/wof-postalcode-json/adapter.d.ts.map +1 -1
- package/out/src/adapters/wof-postalcode-json/adapter.js +2 -2
- package/out/src/adapters/wof-postalcode-json/adapter.js.map +1 -1
- package/out/src/build.d.ts +3 -4
- package/out/src/build.d.ts.map +1 -1
- package/out/src/build.js +6 -8
- package/out/src/build.js.map +1 -1
- package/out/src/index.d.ts +3 -17
- package/out/src/index.d.ts.map +1 -1
- package/out/src/index.js +3 -17
- package/out/src/index.js.map +1 -1
- package/out/src/name-prone-us-suffixes.d.ts +12 -0
- package/out/src/name-prone-us-suffixes.d.ts.map +1 -0
- package/out/src/name-prone-us-suffixes.js +12 -0
- package/out/src/name-prone-us-suffixes.js.map +1 -0
- package/out/src/parquet-wrapper/reader.d.ts +8 -0
- package/out/src/parquet-wrapper/reader.d.ts.map +1 -1
- package/out/src/parquet-wrapper/reader.js +16 -0
- package/out/src/parquet-wrapper/reader.js.map +1 -1
- package/out/src/parquet-wrapper/schema.d.ts +4 -0
- package/out/src/parquet-wrapper/schema.d.ts.map +1 -1
- package/out/src/parquet-wrapper/schema.js.map +1 -1
- package/out/src/runner.d.ts +2 -2
- package/out/src/runner.d.ts.map +1 -1
- package/out/src/runner.js +1 -1
- package/out/src/runner.js.map +1 -1
- package/out/src/shard-recipes/anchor-absorption.d.ts.map +1 -1
- package/out/src/shard-recipes/anchor-absorption.js +5 -4
- package/out/src/shard-recipes/anchor-absorption.js.map +1 -1
- package/out/src/shard-recipes/boundary-stress.d.ts.map +1 -1
- package/out/src/shard-recipes/boundary-stress.js +2 -2
- package/out/src/shard-recipes/boundary-stress.js.map +1 -1
- package/out/src/shard-recipes/country-balanced.d.ts.map +1 -1
- package/out/src/shard-recipes/country-balanced.js +75 -75
- package/out/src/shard-recipes/country-balanced.js.map +1 -1
- package/out/src/shard-recipes/fr-admin-split.js +2 -2
- package/out/src/shard-recipes/fr-admin-split.js.map +1 -1
- package/out/src/shard-recipes/fr-fragment.d.ts.map +1 -1
- package/out/src/shard-recipes/fr-fragment.js +8 -5
- package/out/src/shard-recipes/fr-fragment.js.map +1 -1
- package/out/src/shard-recipes/fr-lieudit.js +2 -2
- package/out/src/shard-recipes/fr-lieudit.js.map +1 -1
- package/out/src/shard-recipes/fr-order.d.ts.map +1 -1
- package/out/src/shard-recipes/fr-order.js +18 -72
- package/out/src/shard-recipes/fr-order.js.map +1 -1
- package/out/src/shard-recipes/german.d.ts.map +1 -1
- package/out/src/shard-recipes/german.js +17 -70
- package/out/src/shard-recipes/german.js.map +1 -1
- package/out/src/shard-recipes/house-venue.d.ts.map +1 -1
- package/out/src/shard-recipes/house-venue.js +1 -1
- package/out/src/shard-recipes/house-venue.js.map +1 -1
- package/out/src/shard-recipes/index.d.ts.map +1 -1
- package/out/src/shard-recipes/index.js +4 -1
- package/out/src/shard-recipes/index.js.map +1 -1
- package/out/src/shard-recipes/intersection.d.ts +2 -2
- package/out/src/shard-recipes/intersection.d.ts.map +1 -1
- package/out/src/shard-recipes/intersection.js +28 -72
- package/out/src/shard-recipes/intersection.js.map +1 -1
- package/out/src/shard-recipes/locale.d.ts +5 -5
- package/out/src/shard-recipes/locale.d.ts.map +1 -1
- package/out/src/shard-recipes/locale.js +25 -35
- package/out/src/shard-recipes/locale.js.map +1 -1
- package/out/src/shard-recipes/no-fragment.d.ts.map +1 -1
- package/out/src/shard-recipes/no-fragment.js +8 -5
- package/out/src/shard-recipes/no-fragment.js.map +1 -1
- package/out/src/shard-recipes/no-street-led.d.ts.map +1 -1
- package/out/src/shard-recipes/no-street-led.js +8 -5
- package/out/src/shard-recipes/no-street-led.js.map +1 -1
- package/out/src/shard-recipes/no-street.d.ts.map +1 -1
- package/out/src/shard-recipes/no-street.js +1 -1
- package/out/src/shard-recipes/no-street.js.map +1 -1
- package/out/src/shard-recipes/po-box-cedex.d.ts +3 -3
- package/out/src/shard-recipes/po-box-cedex.d.ts.map +1 -1
- package/out/src/shard-recipes/po-box-cedex.js +101 -127
- package/out/src/shard-recipes/po-box-cedex.js.map +1 -1
- package/out/src/shard-recipes/po-box.d.ts.map +1 -1
- package/out/src/shard-recipes/po-box.js +1 -1
- package/out/src/shard-recipes/po-box.js.map +1 -1
- package/out/src/shard-recipes/scaffold.d.ts +58 -9
- package/out/src/shard-recipes/scaffold.d.ts.map +1 -1
- package/out/src/shard-recipes/scaffold.js +87 -29
- package/out/src/shard-recipes/scaffold.js.map +1 -1
- package/out/src/shard-recipes/street-affix.d.ts +54 -0
- package/out/src/shard-recipes/street-affix.d.ts.map +1 -1
- package/out/src/shard-recipes/street-affix.js +253 -111
- package/out/src/shard-recipes/street-affix.js.map +1 -1
- package/out/src/shard-recipes/street-bare.d.ts.map +1 -1
- package/out/src/shard-recipes/street-bare.js +3 -3
- package/out/src/shard-recipes/street-bare.js.map +1 -1
- package/out/src/shard-recipes/street.d.ts.map +1 -1
- package/out/src/shard-recipes/street.js +2 -2
- package/out/src/shard-recipes/street.js.map +1 -1
- package/out/src/shard-recipes/sub-venue-sources.d.ts +228 -0
- package/out/src/shard-recipes/sub-venue-sources.d.ts.map +1 -0
- package/out/src/shard-recipes/sub-venue-sources.js +664 -0
- package/out/src/shard-recipes/sub-venue-sources.js.map +1 -0
- package/out/src/shard-recipes/sub-venue.d.ts +269 -0
- package/out/src/shard-recipes/sub-venue.d.ts.map +1 -0
- package/out/src/shard-recipes/sub-venue.js +709 -0
- package/out/src/shard-recipes/sub-venue.js.map +1 -0
- package/out/src/shard-recipes/unit.d.ts +1 -1
- package/out/src/shard-recipes/unit.d.ts.map +1 -1
- package/out/src/shard-recipes/unit.js +26 -74
- package/out/src/shard-recipes/unit.js.map +1 -1
- package/out/src/{synthesize-anchor-absorption.d.ts → synthesizers/anchor-absorption.d.ts} +1 -1
- package/out/src/synthesizers/anchor-absorption.d.ts.map +1 -0
- package/out/src/{synthesize-anchor-absorption.js → synthesizers/anchor-absorption.js} +1 -1
- package/out/src/synthesizers/anchor-absorption.js.map +1 -0
- package/out/src/{synthesize-boundary-stress.d.ts → synthesizers/boundary-stress.d.ts} +3 -3
- package/out/src/synthesizers/boundary-stress.d.ts.map +1 -0
- package/out/src/{synthesize-boundary-stress.js → synthesizers/boundary-stress.js} +2 -2
- package/out/src/synthesizers/boundary-stress.js.map +1 -0
- package/out/src/{synthesize-german.d.ts → synthesizers/german.d.ts} +2 -2
- package/out/src/synthesizers/german.d.ts.map +1 -0
- package/out/src/{synthesize-german.js → synthesizers/german.js} +2 -2
- package/out/src/synthesizers/german.js.map +1 -0
- package/out/src/{synthesize-house-venue.d.ts → synthesizers/house-venue.d.ts} +4 -4
- package/out/src/synthesizers/house-venue.d.ts.map +1 -0
- package/out/src/{synthesize-house-venue.js → synthesizers/house-venue.js} +4 -4
- package/out/src/synthesizers/house-venue.js.map +1 -0
- package/out/src/{synthesize-intersection.d.ts → synthesizers/intersection.d.ts} +2 -2
- package/out/src/synthesizers/intersection.d.ts.map +1 -0
- package/out/src/{synthesize-intersection.js → synthesizers/intersection.js} +1 -1
- package/out/src/synthesizers/intersection.js.map +1 -0
- package/out/src/{synthesize-no-street.d.ts → synthesizers/no-street.d.ts} +3 -3
- package/out/src/synthesizers/no-street.d.ts.map +1 -0
- package/out/src/{synthesize-no-street.js → synthesizers/no-street.js} +2 -2
- package/out/src/synthesizers/no-street.js.map +1 -0
- package/out/src/{synthesize-po-box.d.ts → synthesizers/po-box.d.ts} +2 -2
- package/out/src/synthesizers/po-box.d.ts.map +1 -0
- package/out/src/{synthesize-po-box.js → synthesizers/po-box.js} +1 -1
- package/out/src/synthesizers/po-box.js.map +1 -0
- package/out/src/{synthesize-street.d.ts → synthesizers/street.d.ts} +2 -2
- package/out/src/synthesizers/street.d.ts.map +1 -0
- package/out/src/{synthesize-street.js → synthesizers/street.js} +2 -2
- package/out/src/synthesizers/street.js.map +1 -0
- package/out/src/{synthesize.d.ts → synthesizers/utils.d.ts} +3 -3
- package/out/src/synthesizers/utils.d.ts.map +1 -0
- package/out/src/{synthesize.js → synthesizers/utils.js} +4 -15
- package/out/src/synthesizers/utils.js.map +1 -0
- package/out/src/tools/align-shard.d.ts.map +1 -1
- package/out/src/tools/align-shard.js +4 -8
- package/out/src/tools/align-shard.js.map +1 -1
- package/out/src/tools/audit.d.ts.map +1 -1
- package/out/src/tools/audit.js +4 -4
- package/out/src/tools/audit.js.map +1 -1
- package/out/src/tools/corpus-stats.d.ts +2 -2
- package/out/src/tools/corpus-stats.d.ts.map +1 -1
- package/out/src/tools/corpus-stats.js +18 -31
- package/out/src/tools/corpus-stats.js.map +1 -1
- package/out/src/tools/fetch/download.d.ts.map +1 -1
- package/out/src/tools/fetch/download.js +5 -6
- package/out/src/tools/fetch/download.js.map +1 -1
- package/out/src/tools/fetch/imls-pls.d.ts.map +1 -1
- package/out/src/tools/fetch/imls-pls.js +3 -15
- package/out/src/tools/fetch/imls-pls.js.map +1 -1
- package/out/src/tools/fetch/index.d.ts +14 -1
- package/out/src/tools/fetch/index.d.ts.map +1 -1
- package/out/src/tools/fetch/index.js +14 -1
- package/out/src/tools/fetch/index.js.map +1 -1
- package/out/src/tools/fetch/nad.d.ts +1 -1
- package/out/src/tools/fetch/nad.js +1 -1
- package/out/src/tools/fetch/nppes.d.ts.map +1 -1
- package/out/src/tools/fetch/nppes.js +8 -14
- package/out/src/tools/fetch/nppes.js.map +1 -1
- package/out/src/tools/fetch/openaddresses.d.ts +1 -1
- package/out/src/tools/fetch/openaddresses.js +1 -1
- package/out/src/tools/fetch/ourairports.d.ts +45 -0
- package/out/src/tools/fetch/ourairports.d.ts.map +1 -0
- package/out/src/tools/fetch/ourairports.js +123 -0
- package/out/src/tools/fetch/ourairports.js.map +1 -0
- package/out/src/tools/fetch/wikidata-subvenue.d.ts +171 -0
- package/out/src/tools/fetch/wikidata-subvenue.d.ts.map +1 -0
- package/out/src/tools/fetch/wikidata-subvenue.js +275 -0
- package/out/src/tools/fetch/wikidata-subvenue.js.map +1 -0
- package/out/src/tools/golden-expand.d.ts.map +1 -1
- package/out/src/tools/golden-expand.js +18 -16
- package/out/src/tools/golden-expand.js.map +1 -1
- package/out/src/tools/golden-promote.d.ts.map +1 -1
- package/out/src/tools/golden-promote.js +12 -6
- package/out/src/tools/golden-promote.js.map +1 -1
- package/out/src/tools/golden-relabel-street.d.ts +196 -0
- package/out/src/tools/golden-relabel-street.d.ts.map +1 -0
- package/out/src/tools/golden-relabel-street.js +440 -0
- package/out/src/tools/golden-relabel-street.js.map +1 -0
- package/out/src/tools/index.d.ts +4 -0
- package/out/src/tools/index.d.ts.map +1 -1
- package/out/src/tools/index.js +4 -0
- package/out/src/tools/index.js.map +1 -1
- package/out/src/tools/jsonl-to-parquet.d.ts.map +1 -1
- package/out/src/tools/jsonl-to-parquet.js +3 -2
- package/out/src/tools/jsonl-to-parquet.js.map +1 -1
- package/out/src/tools/lint-shard-vocab.d.ts.map +1 -1
- package/out/src/tools/lint-shard-vocab.js +3 -2
- package/out/src/tools/lint-shard-vocab.js.map +1 -1
- package/out/src/tools/lint-shard.d.ts +3 -3
- package/out/src/tools/lint-shard.d.ts.map +1 -1
- package/out/src/tools/lint-shard.js +23 -32
- package/out/src/tools/lint-shard.js.map +1 -1
- package/out/src/tools/overlay-manifest.d.ts.map +1 -1
- package/out/src/tools/overlay-manifest.js +2 -1
- package/out/src/tools/overlay-manifest.js.map +1 -1
- package/out/src/tools/overture-subvenue.d.ts +112 -0
- package/out/src/tools/overture-subvenue.d.ts.map +1 -0
- package/out/src/tools/overture-subvenue.js +144 -0
- package/out/src/tools/overture-subvenue.js.map +1 -0
- package/out/src/tools/shard-kryptonite.d.ts +1 -1
- package/out/src/tools/shard-kryptonite.d.ts.map +1 -1
- package/out/src/tools/shard-kryptonite.js +6 -6
- package/out/src/tools/shard-kryptonite.js.map +1 -1
- package/out/src/tools/shard-translit.d.ts +6 -3
- package/out/src/tools/shard-translit.d.ts.map +1 -1
- package/out/src/tools/shard-translit.js +9 -8
- package/out/src/tools/shard-translit.js.map +1 -1
- package/out/src/tools/sub-venue-lexicon.d.ts +507 -0
- package/out/src/tools/sub-venue-lexicon.d.ts.map +1 -0
- package/out/src/tools/sub-venue-lexicon.js +817 -0
- package/out/src/tools/sub-venue-lexicon.js.map +1 -0
- package/out/src/tools/sub-venue-promotions.d.ts +94 -0
- package/out/src/tools/sub-venue-promotions.d.ts.map +1 -0
- package/out/src/tools/sub-venue-promotions.js +266 -0
- package/out/src/tools/sub-venue-promotions.js.map +1 -0
- package/out/src/{align.d.ts → utils/align.d.ts} +1 -1
- package/out/src/utils/align.d.ts.map +1 -0
- package/out/src/utils/align.js.map +1 -0
- package/out/src/{golden.d.ts → utils/golden.d.ts} +5 -0
- package/out/src/utils/golden.d.ts.map +1 -0
- package/out/src/{golden.js → utils/golden.js} +24 -10
- package/out/src/utils/golden.js.map +1 -0
- package/out/src/utils/index.d.ts +14 -0
- package/out/src/utils/index.d.ts.map +1 -0
- package/out/src/utils/index.js +14 -0
- package/out/src/utils/index.js.map +1 -0
- package/out/src/utils/license.d.ts.map +1 -0
- package/out/src/utils/license.js.map +1 -0
- package/out/src/{parquet.d.ts → utils/parquet.d.ts} +2 -2
- package/out/src/utils/parquet.d.ts.map +1 -0
- package/out/src/{parquet.js → utils/parquet.js} +3 -15
- package/out/src/utils/parquet.js.map +1 -0
- package/out/src/{split.d.ts → utils/split.d.ts} +8 -1
- package/out/src/utils/split.d.ts.map +1 -0
- package/out/src/{split.js → utils/split.js} +7 -0
- package/out/src/utils/split.js.map +1 -0
- package/out/src/utils/tokenize.d.ts.map +1 -0
- package/out/src/utils/tokenize.js.map +1 -0
- package/out/src/{wof-json.d.ts → utils/wof-json.d.ts} +2 -2
- package/out/src/utils/wof-json.d.ts.map +1 -0
- package/out/src/{wof-json.js → utils/wof-json.js} +5 -8
- package/out/src/utils/wof-json.js.map +1 -0
- package/package.json +66 -20
- package/src/adapters/ban/adapter.ts +58 -68
- package/src/adapters/ban/street-decompose.ts +17 -25
- package/src/adapters/fcc-bdc/adapter.ts +5 -36
- package/src/adapters/geonames/adapter.ts +67 -76
- package/src/adapters/geonames-postal/adapter.ts +45 -54
- package/src/adapters/gnaf/adapter.ts +7 -11
- package/src/adapters/gnaf/assemble.ts +7 -11
- package/src/adapters/index.ts +3 -2
- package/src/adapters/openaddresses/adapter.ts +6 -12
- package/src/adapters/overture/adapter.ts +6 -10
- package/src/adapters/state-hi-schools/adapter.ts +53 -77
- package/src/adapters/state-ia-contractors/adapter.ts +55 -80
- package/src/adapters/state-ny-notaries/adapter.ts +64 -89
- package/src/adapters/state-tx-notaries/adapter.ts +63 -88
- package/src/adapters/synth-po-box/adapter.ts +12 -23
- package/src/adapters/tiger/adapter.ts +4 -3
- package/src/adapters/tiger/street-decompose.ts +21 -31
- package/src/adapters/usgov-hrsa-fqhc/adapter.ts +64 -88
- package/src/adapters/usgov-imls-pls/adapter.ts +57 -86
- package/src/adapters/usgov-irs-bmf/adapter.ts +55 -66
- package/src/adapters/usgov-nad/adapter.ts +7 -11
- package/src/adapters/usgov-nppes/adapter.ts +54 -79
- package/src/adapters/usgov-samhsa-treatment-locator/adapter.ts +48 -75
- package/src/{adapter.ts → adapters/utils/index.ts} +59 -3
- package/src/adapters/wof-admin-jp/adapter.ts +35 -9
- package/src/adapters/wof-admin-json/adapter.ts +3 -4
- package/src/adapters/wof-postalcode-json/adapter.ts +3 -4
- package/src/build.ts +12 -11
- package/src/index.ts +3 -17
- package/src/name-prone-us-suffixes.ts +12 -0
- package/src/parquet-wrapper/reader.ts +19 -0
- package/src/parquet-wrapper/schema.ts +4 -0
- package/src/runner.ts +7 -2
- package/src/shard-recipes/anchor-absorption.ts +5 -4
- package/src/shard-recipes/boundary-stress.ts +6 -2
- package/src/shard-recipes/country-balanced.ts +77 -91
- package/src/shard-recipes/fr-admin-split.ts +3 -3
- package/src/shard-recipes/fr-fragment.ts +10 -7
- package/src/shard-recipes/fr-lieudit.ts +3 -3
- package/src/shard-recipes/fr-order.ts +18 -83
- package/src/shard-recipes/german.ts +17 -80
- package/src/shard-recipes/house-venue.ts +2 -1
- package/src/shard-recipes/index.ts +4 -1
- package/src/shard-recipes/intersection.ts +37 -74
- package/src/shard-recipes/locale.ts +31 -39
- package/src/shard-recipes/no-fragment.ts +10 -7
- package/src/shard-recipes/no-street-led.ts +10 -7
- package/src/shard-recipes/no-street.ts +2 -1
- package/src/shard-recipes/po-box-cedex.ts +127 -161
- package/src/shard-recipes/po-box.ts +6 -1
- package/src/shard-recipes/scaffold.ts +125 -27
- package/src/shard-recipes/street-affix.ts +335 -134
- package/src/shard-recipes/street-bare.ts +4 -3
- package/src/shard-recipes/street.ts +3 -2
- package/src/shard-recipes/sub-venue-sources.ts +895 -0
- package/src/shard-recipes/sub-venue.ts +982 -0
- package/src/shard-recipes/unit.ts +27 -85
- package/src/{synthesize-boundary-stress.ts → synthesizers/boundary-stress.ts} +2 -2
- package/src/{synthesize-german.ts → synthesizers/german.ts} +2 -2
- package/src/{synthesize-house-venue.ts → synthesizers/house-venue.ts} +4 -4
- package/src/{synthesize-intersection.ts → synthesizers/intersection.ts} +1 -1
- package/src/{synthesize-no-street.ts → synthesizers/no-street.ts} +2 -2
- package/src/{synthesize-po-box.ts → synthesizers/po-box.ts} +1 -1
- package/src/{synthesize-street.ts → synthesizers/street.ts} +2 -2
- package/src/{synthesize.ts → synthesizers/utils.ts} +4 -18
- package/src/tools/align-shard.ts +4 -7
- package/src/tools/audit.ts +6 -5
- package/src/tools/corpus-stats.ts +25 -33
- package/src/tools/fetch/download.ts +7 -5
- package/src/tools/fetch/imls-pls.ts +4 -18
- package/src/tools/fetch/index.ts +14 -1
- package/src/tools/fetch/nad.ts +1 -1
- package/src/tools/fetch/nppes.ts +9 -16
- package/src/tools/fetch/openaddresses.ts +1 -1
- package/src/tools/fetch/ourairports.ts +166 -0
- package/src/tools/fetch/wikidata-subvenue.ts +386 -0
- package/src/tools/golden-expand.ts +18 -13
- package/src/tools/golden-promote.ts +15 -6
- package/src/tools/golden-relabel-street.ts +685 -0
- package/src/tools/index.ts +4 -0
- package/src/tools/jsonl-to-parquet.ts +3 -2
- package/src/tools/lint-shard-vocab.ts +3 -2
- package/src/tools/lint-shard.ts +33 -36
- package/src/tools/overlay-manifest.ts +2 -1
- package/src/tools/overture-subvenue.ts +215 -0
- package/src/tools/shard-kryptonite.ts +8 -9
- package/src/tools/shard-translit.ts +22 -11
- package/src/tools/sub-venue-lexicon.ts +1250 -0
- package/src/tools/sub-venue-promotions.ts +330 -0
- package/src/{align.ts → utils/align.ts} +1 -1
- package/src/{golden.ts → utils/golden.ts} +25 -11
- package/src/utils/index.ts +14 -0
- package/src/{parquet.ts → utils/parquet.ts} +5 -19
- package/src/{split.ts → utils/split.ts} +8 -2
- package/src/{wof-json.ts → utils/wof-json.ts} +5 -8
- package/out/src/adapter.d.ts.map +0 -1
- package/out/src/adapter.js.map +0 -1
- package/out/src/align.d.ts.map +0 -1
- package/out/src/align.js.map +0 -1
- package/out/src/format.d.ts +0 -14
- package/out/src/format.d.ts.map +0 -1
- package/out/src/format.js +0 -14
- package/out/src/format.js.map +0 -1
- package/out/src/golden.d.ts.map +0 -1
- package/out/src/golden.js.map +0 -1
- package/out/src/license.d.ts.map +0 -1
- package/out/src/license.js.map +0 -1
- package/out/src/parquet.d.ts.map +0 -1
- package/out/src/parquet.js.map +0 -1
- package/out/src/split.d.ts.map +0 -1
- package/out/src/split.js.map +0 -1
- package/out/src/synthesize-anchor-absorption.d.ts.map +0 -1
- package/out/src/synthesize-anchor-absorption.js.map +0 -1
- package/out/src/synthesize-boundary-stress.d.ts.map +0 -1
- package/out/src/synthesize-boundary-stress.js.map +0 -1
- package/out/src/synthesize-german.d.ts.map +0 -1
- package/out/src/synthesize-german.js.map +0 -1
- package/out/src/synthesize-house-venue.d.ts.map +0 -1
- package/out/src/synthesize-house-venue.js.map +0 -1
- package/out/src/synthesize-intersection.d.ts.map +0 -1
- package/out/src/synthesize-intersection.js.map +0 -1
- package/out/src/synthesize-no-street.d.ts.map +0 -1
- package/out/src/synthesize-no-street.js.map +0 -1
- package/out/src/synthesize-po-box.d.ts.map +0 -1
- package/out/src/synthesize-po-box.js.map +0 -1
- package/out/src/synthesize-street.d.ts.map +0 -1
- package/out/src/synthesize-street.js.map +0 -1
- package/out/src/synthesize.d.ts.map +0 -1
- package/out/src/synthesize.js.map +0 -1
- package/out/src/tokenize.d.ts.map +0 -1
- package/out/src/tokenize.js.map +0 -1
- package/out/src/wof-json.d.ts.map +0 -1
- package/out/src/wof-json.js.map +0 -1
- package/src/format.ts +0 -14
- /package/out/src/{align.js → utils/align.js} +0 -0
- /package/out/src/{license.d.ts → utils/license.d.ts} +0 -0
- /package/out/src/{license.js → utils/license.js} +0 -0
- /package/out/src/{tokenize.d.ts → utils/tokenize.d.ts} +0 -0
- /package/out/src/{tokenize.js → utils/tokenize.js} +0 -0
- /package/src/{synthesize-anchor-absorption.ts → synthesizers/anchor-absorption.ts} +0 -0
- /package/src/{license.ts → utils/license.ts} +0 -0
- /package/src/{tokenize.ts → utils/tokenize.ts} +0 -0
|
@@ -27,8 +27,6 @@
|
|
|
27
27
|
* FR/DE postcode (the v0.9.8 blemish).
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import { spawnSync } from "node:child_process"
|
|
31
|
-
|
|
32
30
|
import {
|
|
33
31
|
DirectionalAbbreviation,
|
|
34
32
|
lookupDirectional,
|
|
@@ -39,11 +37,13 @@ import {
|
|
|
39
37
|
US_STREET_SUFFIX_PREFERRED_ABBR,
|
|
40
38
|
} from "@mailwoman/codex/us"
|
|
41
39
|
import type { ComponentTag } from "@mailwoman/core/types"
|
|
40
|
+
import { dataRootPath } from "@mailwoman/core/utils"
|
|
41
|
+
import { stableSourceID } from "@mailwoman/corpus/adapters/utils"
|
|
42
|
+
import type { CanonicalRow } from "@mailwoman/corpus/types"
|
|
43
|
+
import { alignRow } from "@mailwoman/corpus/utils"
|
|
42
44
|
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import type { CanonicalRow } from "../types.ts"
|
|
46
|
-
import { makeMulberry32, type ShardRecipe } from "./scaffold.ts"
|
|
45
|
+
import { NAME_PRONE_US_SUFFIXES } from "../name-prone-us-suffixes.ts"
|
|
46
|
+
import { makeMulberry32, readCSVRecords, readZippedCSVRecords, shardSourceID, type ShardRecipe } from "./scaffold.ts"
|
|
47
47
|
|
|
48
48
|
// Same OA cache as the unit shard. Train = every NON-Vermont state; eval = Vermont (the holdout).
|
|
49
49
|
/* oxlint-disable sister-software/no-unnamed-threshold -- the bare decimals below are weighted-sampler
|
|
@@ -59,16 +59,20 @@ interface USSource {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
const TRAIN_SOURCES: readonly USSource[] = [
|
|
62
|
-
{ zip: "
|
|
63
|
-
{ zip: "
|
|
64
|
-
{ zip: "
|
|
65
|
-
{ zip: "
|
|
66
|
-
{ zip: "
|
|
67
|
-
{ zip: "
|
|
68
|
-
{ zip: "
|
|
62
|
+
{ zip: dataRootPath("oa-cache", "us__ca__berkeley.zip"), csv: "us/ca/berkeley.csv", region: "CA" },
|
|
63
|
+
{ zip: dataRootPath("oa-cache", "us__ca__marin.zip"), csv: "us/ca/marin.csv", region: "CA" },
|
|
64
|
+
{ zip: dataRootPath("oa-cache", "us__dc__statewide.zip"), csv: "us/dc/statewide.csv", region: "DC" },
|
|
65
|
+
{ zip: dataRootPath("oa-cache", "us__ia__statewide.zip"), csv: "us/ia/statewide.csv", region: "IA" },
|
|
66
|
+
{ zip: dataRootPath("oa-cache", "us__il__cook.zip"), csv: "us/il/cook.csv", region: "IL" },
|
|
67
|
+
{ zip: dataRootPath("oa-cache", "us__mt__statewide.zip"), csv: "us/mt/statewide.csv", region: "MT" },
|
|
68
|
+
{ zip: dataRootPath("oa-cache", "us__sd__statewide.zip"), csv: "us/sd/statewide.csv", region: "SD" },
|
|
69
69
|
]
|
|
70
70
|
|
|
71
|
-
const EVAL_SOURCE: USSource = {
|
|
71
|
+
const EVAL_SOURCE: USSource = {
|
|
72
|
+
zip: dataRootPath("oa-cache", "us__vt__statewide.zip"),
|
|
73
|
+
csv: "us/vt/statewide.csv",
|
|
74
|
+
region: "VT",
|
|
75
|
+
}
|
|
72
76
|
|
|
73
77
|
// Multi-locale BALANCE sources (--multilocale-count > 0). These rows carry NO affix split — they exist
|
|
74
78
|
// only to keep the postcode-ORDER distribution multi-locale. Native-order rendering mirrors
|
|
@@ -83,14 +87,38 @@ interface BalanceSource {
|
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
const MULTILOCALE_SOURCES: readonly BalanceSource[] = [
|
|
86
|
-
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
{
|
|
91
|
+
zip: dataRootPath("oa-cache", "de__sn__statewide.zip"),
|
|
92
|
+
csv: "de/sn/statewide.csv",
|
|
93
|
+
iso2: "DE",
|
|
94
|
+
region: "",
|
|
95
|
+
order: "eu",
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
zip: dataRootPath("oa-cache", "fr__countrywide.zip"),
|
|
99
|
+
csv: "fr/countrywide.csv",
|
|
100
|
+
iso2: "FR",
|
|
101
|
+
region: "",
|
|
102
|
+
order: "fr",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
zip: dataRootPath("oa-cache", "it__countrywide.zip"),
|
|
106
|
+
csv: "it/countrywide.csv",
|
|
107
|
+
iso2: "IT",
|
|
108
|
+
region: "",
|
|
109
|
+
order: "eu",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
zip: dataRootPath("oa-cache", "nl__countrywide.zip"),
|
|
113
|
+
csv: "nl/countrywide.csv",
|
|
114
|
+
iso2: "NL",
|
|
115
|
+
region: "",
|
|
116
|
+
order: "eu",
|
|
117
|
+
},
|
|
90
118
|
]
|
|
91
119
|
|
|
92
120
|
const MULTILOCALE_EVAL_SOURCES: readonly BalanceSource[] = [
|
|
93
|
-
{ zip: "
|
|
121
|
+
{ zip: dataRootPath("oa-cache", "de__berlin.zip"), csv: "de/berlin.csv", iso2: "DE", region: "", order: "eu" },
|
|
94
122
|
]
|
|
95
123
|
|
|
96
124
|
/**
|
|
@@ -111,6 +139,7 @@ interface USTuple {
|
|
|
111
139
|
locality: string
|
|
112
140
|
region: string
|
|
113
141
|
postcode: string
|
|
142
|
+
base_source_id: string
|
|
114
143
|
}
|
|
115
144
|
|
|
116
145
|
/**
|
|
@@ -131,84 +160,32 @@ interface BalanceTuple {
|
|
|
131
160
|
*/
|
|
132
161
|
type Prefix = Pick<NonNullable<ReturnType<typeof matchLeadingDirectional>>, "canonical" | "abbreviation">
|
|
133
162
|
|
|
134
|
-
/**
|
|
135
|
-
* Minimal RFC-4180-ish splitter (handles quoted fields).
|
|
136
|
-
*/
|
|
137
|
-
function splitCSV(line: string): string[] {
|
|
138
|
-
const out: string[] = []
|
|
139
|
-
let cur = ""
|
|
140
|
-
let inQ = false
|
|
141
|
-
|
|
142
|
-
for (let i = 0; i < line.length; i++) {
|
|
143
|
-
const c = line[i]
|
|
144
|
-
|
|
145
|
-
if (inQ) {
|
|
146
|
-
if (c === '"') {
|
|
147
|
-
if (line[i + 1] === '"') {
|
|
148
|
-
cur += '"'
|
|
149
|
-
|
|
150
|
-
i++
|
|
151
|
-
} else {
|
|
152
|
-
inQ = false
|
|
153
|
-
}
|
|
154
|
-
} else {
|
|
155
|
-
cur += c
|
|
156
|
-
}
|
|
157
|
-
} else if (c === '"') {
|
|
158
|
-
inQ = true
|
|
159
|
-
} else if (c === ",") {
|
|
160
|
-
out.push(cur)
|
|
161
|
-
cur = ""
|
|
162
|
-
} else {
|
|
163
|
-
cur += c
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
out.push(cur)
|
|
168
|
-
|
|
169
|
-
return out
|
|
170
|
-
}
|
|
171
|
-
|
|
172
163
|
/**
|
|
173
164
|
* Stream real US tuples (number/street/city/postcode) out of a cached OA zip.
|
|
174
165
|
*/
|
|
175
|
-
function readTuples(source: USSource): USTuple[] {
|
|
176
|
-
const r = spawnSync("unzip", ["-p", source.zip, source.csv], { maxBuffer: 1024 * 1024 * 1024, encoding: "buffer" })
|
|
177
|
-
|
|
178
|
-
if (r.status !== 0) {
|
|
179
|
-
console.error(` WARN: unzip failed for ${source.zip} (status ${r.status})`)
|
|
180
|
-
|
|
181
|
-
return []
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const lines = r.stdout.toString("utf8").split(/\r?\n/)
|
|
185
|
-
|
|
186
|
-
if (lines.length < 2) return []
|
|
187
|
-
const header = splitCSV(lines[0]!).map((h) => h.trim().toLowerCase())
|
|
188
|
-
const idx = (name: string): number => header.indexOf(name)
|
|
189
|
-
|
|
190
|
-
const iNum = idx("number"),
|
|
191
|
-
iStreet = idx("street"),
|
|
192
|
-
iCity = idx("city"),
|
|
193
|
-
iPost = idx("postcode")
|
|
194
|
-
|
|
195
|
-
const get = (cells: string[], i: number): string => (i >= 0 && i < cells.length ? (cells[i] ?? "").trim() : "")
|
|
166
|
+
async function readTuples(source: USSource): Promise<USTuple[]> {
|
|
196
167
|
const tuples: USTuple[] = []
|
|
197
168
|
const seen = new Set<string>()
|
|
198
169
|
|
|
199
|
-
for (
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
const locality = get(cells, iCity)
|
|
204
|
-
const house_number = get(cells, iNum)
|
|
170
|
+
for await (const row of readZippedCSVRecords(source.zip, source.csv)) {
|
|
171
|
+
const street = row.street ?? ""
|
|
172
|
+
const locality = row.city ?? ""
|
|
173
|
+
const house_number = row.number ?? ""
|
|
205
174
|
|
|
206
175
|
if (!street || !locality || !house_number) continue
|
|
207
176
|
const key = `${house_number}|${street}|${locality}`.toLowerCase()
|
|
208
177
|
|
|
209
178
|
if (seen.has(key)) continue
|
|
210
179
|
seen.add(key)
|
|
211
|
-
|
|
180
|
+
|
|
181
|
+
tuples.push({
|
|
182
|
+
house_number,
|
|
183
|
+
street,
|
|
184
|
+
locality,
|
|
185
|
+
region: source.region,
|
|
186
|
+
postcode: row.postcode ?? "",
|
|
187
|
+
base_source_id: `openaddresses:${source.csv}:${key}`,
|
|
188
|
+
})
|
|
212
189
|
}
|
|
213
190
|
|
|
214
191
|
return tuples
|
|
@@ -228,7 +205,10 @@ const isSuffixOrDirectional = (word: string): boolean =>
|
|
|
228
205
|
* Split an OA street into { prefix?, name, suffix } using the codex. Requires a trailing suffix and a non-empty name
|
|
229
206
|
* that isn't itself an affix token. Returns null when the street has no usable suffix.
|
|
230
207
|
*/
|
|
231
|
-
function parseStreet(
|
|
208
|
+
function parseStreet(
|
|
209
|
+
street: string,
|
|
210
|
+
opts: { allowNameProneTail?: boolean } = {}
|
|
211
|
+
): { prefix: Prefix | null; name: string; suffix: string } | null {
|
|
232
212
|
let words = street.trim().split(/\s+/)
|
|
233
213
|
|
|
234
214
|
if (words.length < 2) return null
|
|
@@ -248,11 +228,42 @@ function parseStreet(street: string): { prefix: Prefix | null; name: string; suf
|
|
|
248
228
|
const suffix = trail.canonical
|
|
249
229
|
const name = words.slice(0, -1).join(" ")
|
|
250
230
|
|
|
251
|
-
if (!name
|
|
231
|
+
if (!name) return null
|
|
232
|
+
|
|
233
|
+
if (isSuffixOrDirectional(name)) {
|
|
234
|
+
const nameTail = matchTrailingSuffix(name)
|
|
235
|
+
|
|
236
|
+
if (!opts.allowNameProneTail || !nameTail || !NAME_PRONE_US_SUFFIXES.has(nameTail.canonical)) return null
|
|
237
|
+
}
|
|
252
238
|
|
|
253
239
|
return { prefix, name, suffix }
|
|
254
240
|
}
|
|
255
241
|
|
|
242
|
+
export type SuffixBoundaryClass = "terminal-only" | "terminal-contrast"
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Classify a real street surface for #1569. `terminal-only` has an ambiguous suffix-eligible name word immediately
|
|
246
|
+
* before a different terminal type (`Blue Hill Rd`); `terminal-contrast` ends at the ambiguous word itself (`Sutton
|
|
247
|
+
* Hollow`). The contrast check intentionally wins when both final words are name-prone: only the LAST token is the
|
|
248
|
+
* suffix under the canonical rule.
|
|
249
|
+
*/
|
|
250
|
+
export function classifySuffixBoundaryStreet(street: string): SuffixBoundaryClass | null {
|
|
251
|
+
const words = street.trim().split(/\s+/)
|
|
252
|
+
|
|
253
|
+
if (words.length < 2) return null
|
|
254
|
+
const terminal = matchTrailingSuffix(words.at(-1)!)
|
|
255
|
+
|
|
256
|
+
if (!terminal) return null
|
|
257
|
+
|
|
258
|
+
if (NAME_PRONE_US_SUFFIXES.has(terminal.canonical)) return "terminal-contrast"
|
|
259
|
+
|
|
260
|
+
if (words.length < 3) return null
|
|
261
|
+
|
|
262
|
+
const penultimate = matchTrailingSuffix(words.at(-2)!)
|
|
263
|
+
|
|
264
|
+
return penultimate && NAME_PRONE_US_SUFFIXES.has(penultimate.canonical) ? "terminal-only" : null
|
|
265
|
+
}
|
|
266
|
+
|
|
256
267
|
/**
|
|
257
268
|
* Render the affix-split street in random surface forms (abbrev vs expanded per affix), Title-cased.
|
|
258
269
|
*/
|
|
@@ -302,18 +313,65 @@ function renderStreet(
|
|
|
302
313
|
*/
|
|
303
314
|
const VENUES = ["John Doe", "Jane Smith", "Acme Inc", "Wayne Enterprises", "Maria Garcia", "Riverside Clinic"]
|
|
304
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Real-venue pool for the suffix-boundary v2 venue shell (corpus 0.19.0). The 2026-08-10 recipe review found the
|
|
318
|
+
* v0.18.x shard's venue-led rows detectable as templates (six fixed venue strings), and the frozen B1 board's failures
|
|
319
|
+
* concentrate in exactly that shell (rich rows 5/43 vs bare 53/65 at v4.3.3 step-40k). HRSA's health-center site file
|
|
320
|
+
* supplies thousands of REAL US facility names ('Alburg Health Center'-register), US-government public domain, already
|
|
321
|
+
* a corpus source (`usgov-hrsa-fqhc`). Kept verbatim (including the ~11% all-caps names — real register diversity);
|
|
322
|
+
* comma-carrying names are dropped because the venue layout uses commas as its field delimiter.
|
|
323
|
+
*/
|
|
324
|
+
const VENUE_POOL_CSV = dataRootPath(
|
|
325
|
+
"corpus",
|
|
326
|
+
"sources",
|
|
327
|
+
"usgov-hrsa-fqhc",
|
|
328
|
+
"Health_Center_Service_Delivery_and_LookAlike_Sites.csv"
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
async function readVenuePool(csvPath: string): Promise<string[]> {
|
|
332
|
+
const seen = new Set<string>()
|
|
333
|
+
const pool: string[] = []
|
|
334
|
+
|
|
335
|
+
for await (const record of readCSVRecords(csvPath)) {
|
|
336
|
+
const name = (record["site name"] ?? record["Site Name"] ?? "").trim().replaceAll(/\s+/gu, " ")
|
|
337
|
+
|
|
338
|
+
if (name.length < 3 || name.length > 60 || name.includes(",") || !/\p{L}/u.test(name)) continue
|
|
339
|
+
const key = name.toLowerCase()
|
|
340
|
+
|
|
341
|
+
if (seen.has(key)) continue
|
|
342
|
+
seen.add(key)
|
|
343
|
+
pool.push(name)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return pool
|
|
347
|
+
}
|
|
348
|
+
|
|
305
349
|
const tail = (loc: string, reg: string, pc: string): string => (pc ? `${loc}, ${reg} ${pc}` : `${loc}, ${reg}`)
|
|
306
350
|
|
|
351
|
+
/**
|
|
352
|
+
* Layout-shell options for {@link renderRow}. `cuts` are the cumulative random() cutoffs for [full, bare, street-only] —
|
|
353
|
+
* the remainder is the venue shell. Defaults reproduce the original street-affix distribution (40/25/20/15) with the
|
|
354
|
+
* six template venues.
|
|
355
|
+
*/
|
|
356
|
+
interface RenderRowOpts {
|
|
357
|
+
venues?: readonly string[]
|
|
358
|
+
cuts?: readonly [number, number, number]
|
|
359
|
+
}
|
|
360
|
+
|
|
307
361
|
/**
|
|
308
362
|
* Embed the rendered street in a RANDOM layout so the model recognizes affixes wherever the street sits: full address,
|
|
309
363
|
* bare house+street, street-only (pure affix parse), or venue-prefixed.
|
|
310
364
|
*/
|
|
311
|
-
function renderRow(
|
|
365
|
+
export function renderRow(
|
|
312
366
|
random: () => number,
|
|
313
367
|
base: USTuple,
|
|
314
368
|
street: string,
|
|
315
|
-
streetComponents: Partial<Record<ComponentTag, string
|
|
369
|
+
streetComponents: Partial<Record<ComponentTag, string>>,
|
|
370
|
+
opts: RenderRowOpts = {}
|
|
316
371
|
): { fmt: string; raw: string; components: Partial<Record<ComponentTag, string>> } {
|
|
372
|
+
const venues = opts.venues ?? VENUES
|
|
373
|
+
const [fullCut, bareCut, streetOnlyCut] = opts.cuts ?? [0.4, 0.65, 0.85]
|
|
374
|
+
|
|
317
375
|
const hn = base.house_number,
|
|
318
376
|
loc = base.locality,
|
|
319
377
|
reg = base.region,
|
|
@@ -323,17 +381,17 @@ function renderRow(
|
|
|
323
381
|
const withRoad: Partial<Record<ComponentTag, string>> = { house_number: hn, ...streetComponents }
|
|
324
382
|
const r = random()
|
|
325
383
|
|
|
326
|
-
if (r <
|
|
384
|
+
if (r < fullCut)
|
|
327
385
|
return {
|
|
328
386
|
fmt: "full",
|
|
329
387
|
raw: `${road}, ${tail(loc, reg, pc)}`,
|
|
330
388
|
components: { ...withRoad, locality: loc, region: reg, ...(pc ? { postcode: pc } : {}) },
|
|
331
389
|
}
|
|
332
390
|
|
|
333
|
-
if (r <
|
|
391
|
+
if (r < bareCut) return { fmt: "bare", raw: road, components: withRoad }
|
|
334
392
|
|
|
335
|
-
if (r <
|
|
336
|
-
const v =
|
|
393
|
+
if (r < streetOnlyCut) return { fmt: "street-only", raw: street, components: { ...streetComponents } }
|
|
394
|
+
const v = venues[Math.floor(random() * venues.length)]!
|
|
337
395
|
|
|
338
396
|
return {
|
|
339
397
|
fmt: "venue",
|
|
@@ -343,48 +401,21 @@ function renderRow(
|
|
|
343
401
|
}
|
|
344
402
|
|
|
345
403
|
/**
|
|
346
|
-
* Capped reader for the multi-locale BALANCE sources. The FR/IT/NL countrywide extracts are GB-scale
|
|
347
|
-
*
|
|
348
|
-
*
|
|
404
|
+
* Capped reader for the multi-locale BALANCE sources. The FR/IT/NL countrywide extracts are GB-scale, so this reads
|
|
405
|
+
* only as far as `limit` distinct tuples — the `break` closes the reader and releases the archive. Only keeps tuples
|
|
406
|
+
* that carry a POSTCODE.
|
|
349
407
|
*/
|
|
350
|
-
function readBalanceTuples(source: BalanceSource, limit: number): BalanceTuple[] {
|
|
351
|
-
const maxLines = Math.max(limit * 8, 20_000) + 1
|
|
352
|
-
|
|
353
|
-
const r = spawnSync("bash", ["-c", `unzip -p "${source.zip}" "${source.csv}" | head -n ${maxLines}`], {
|
|
354
|
-
maxBuffer: 1024 * 1024 * 1024,
|
|
355
|
-
encoding: "buffer",
|
|
356
|
-
})
|
|
357
|
-
|
|
358
|
-
if (r.status !== 0) {
|
|
359
|
-
console.error(` WARN: unzip failed for ${source.zip} (status ${r.status})`)
|
|
360
|
-
|
|
361
|
-
return []
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const lines = r.stdout.toString("utf8").split(/\r?\n/)
|
|
365
|
-
|
|
366
|
-
if (lines.length < 2) return []
|
|
367
|
-
const header = splitCSV(lines[0]!).map((h) => h.trim().toLowerCase())
|
|
368
|
-
const idx = (n: string): number => header.indexOf(n)
|
|
369
|
-
|
|
370
|
-
const iNum = idx("number"),
|
|
371
|
-
iStreet = idx("street"),
|
|
372
|
-
iCity = idx("city"),
|
|
373
|
-
iRegion = idx("region"),
|
|
374
|
-
iPost = idx("postcode")
|
|
375
|
-
|
|
376
|
-
const get = (cells: string[], i: number): string => (i >= 0 && i < cells.length ? (cells[i] ?? "").trim() : "")
|
|
408
|
+
async function readBalanceTuples(source: BalanceSource, limit: number): Promise<BalanceTuple[]> {
|
|
377
409
|
const tuples: BalanceTuple[] = []
|
|
378
410
|
const seen = new Set<string>()
|
|
379
411
|
|
|
380
|
-
for (
|
|
381
|
-
if (
|
|
382
|
-
const cells = splitCSV(lines[li]!)
|
|
412
|
+
for await (const row of readZippedCSVRecords(source.zip, source.csv)) {
|
|
413
|
+
if (tuples.length >= limit) break
|
|
383
414
|
|
|
384
|
-
const street =
|
|
385
|
-
locality =
|
|
386
|
-
house_number =
|
|
387
|
-
postcode =
|
|
415
|
+
const street = row.street ?? "",
|
|
416
|
+
locality = row.city ?? "",
|
|
417
|
+
house_number = row.number ?? "",
|
|
418
|
+
postcode = row.postcode ?? ""
|
|
388
419
|
|
|
389
420
|
if (!street || !locality || !house_number || !postcode) continue // postcode is required for balance
|
|
390
421
|
const key = `${house_number}|${street}|${locality}`.toLowerCase()
|
|
@@ -396,7 +427,7 @@ function readBalanceTuples(source: BalanceSource, limit: number): BalanceTuple[]
|
|
|
396
427
|
house_number,
|
|
397
428
|
street,
|
|
398
429
|
locality,
|
|
399
|
-
region:
|
|
430
|
+
region: row.region || source.region,
|
|
400
431
|
postcode,
|
|
401
432
|
iso2: source.iso2,
|
|
402
433
|
order: source.order,
|
|
@@ -449,7 +480,7 @@ export const streetAffixRecipe: ShardRecipe = {
|
|
|
449
480
|
const pool: USTuple[] = []
|
|
450
481
|
|
|
451
482
|
for (const s of sources) {
|
|
452
|
-
const t = readTuples(s)
|
|
483
|
+
const t = await readTuples(s)
|
|
453
484
|
|
|
454
485
|
console.error(` ${s.csv}: ${t.length} unique tuples`)
|
|
455
486
|
|
|
@@ -459,7 +490,7 @@ export const streetAffixRecipe: ShardRecipe = {
|
|
|
459
490
|
}
|
|
460
491
|
|
|
461
492
|
if (!pool.length) {
|
|
462
|
-
throw new Error(
|
|
493
|
+
throw new Error(`No US tuples found — are the cached OA zips present in ${dataRootPath("oa-cache")}?`)
|
|
463
494
|
}
|
|
464
495
|
|
|
465
496
|
let emitted = 0
|
|
@@ -550,7 +581,7 @@ export const streetAffixRecipe: ShardRecipe = {
|
|
|
550
581
|
const mlPool: BalanceTuple[] = []
|
|
551
582
|
|
|
552
583
|
for (const s of mlSources) {
|
|
553
|
-
const t = readBalanceTuples(s, perSource)
|
|
584
|
+
const t = await readBalanceTuples(s, perSource)
|
|
554
585
|
|
|
555
586
|
console.error(` balance ${s.csv} (${s.iso2}): ${t.length} tuples`)
|
|
556
587
|
|
|
@@ -622,3 +653,173 @@ export const streetAffixRecipe: ShardRecipe = {
|
|
|
622
653
|
return { emitted: emitted + balanceEmitted, skipped: skipped + balanceSkipped }
|
|
623
654
|
},
|
|
624
655
|
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* #1569 root-fix shard. Both classes come from real non-Vermont OA streets and use the affix recipe's existing layout
|
|
659
|
+
* diversity. v4.3.1 makes terminal-only 80% of the mix: the first 40/60 run moved a 100-row TRAIN sample only 4→11
|
|
660
|
+
* while contrast was already 95/100 before training (93/100 after). Post-run audit found that the global affix relabel
|
|
661
|
+
* pass corrupts many already-decomposed target rows into double suffixes; do not retrain this recipe until relabel is
|
|
662
|
+
* idempotent over a decomposed street family. The 20% contrast leg remains explicit, additive to the already-strong
|
|
663
|
+
* base distribution, and B2 still gates it unchanged.
|
|
664
|
+
*
|
|
665
|
+
* V2 (corpus 0.19.0, 2026-08-10 recipe review): the v4.3.3 board split (rich venue-led rows 5/43 vs bare 53/65) showed
|
|
666
|
+
* the model separating template rows from real ones, and the venue shell was the giveaway — six fixed venue strings. v2
|
|
667
|
+
* draws the venue shell from thousands of REAL HRSA facility names and raises its share (venue 30%, full 35%, bare 20%,
|
|
668
|
+
* street-only 15%). Dose policy moved to the recipe's config side: weight ≤4 effective passes per run (Muennighoff
|
|
669
|
+
* 2023's repetition knee) and the source is excluded from the augmentation pool — see the v4.4.0 config.
|
|
670
|
+
*/
|
|
671
|
+
export const suffixBoundaryRecipe: ShardRecipe = {
|
|
672
|
+
name: "suffix-boundary",
|
|
673
|
+
description: "US #1569 suffix boundary: OA terminal-only positives + over-sampled terminal contrasts",
|
|
674
|
+
mode: "generate",
|
|
675
|
+
async run(opts, write) {
|
|
676
|
+
const random = makeMulberry32(opts.seed)
|
|
677
|
+
const count = opts.count ?? 30_000
|
|
678
|
+
const source = opts.sourceName ?? "synth-suffix-boundary"
|
|
679
|
+
const sources = opts.golden ? [EVAL_SOURCE] : TRAIN_SOURCES
|
|
680
|
+
|
|
681
|
+
// v2 venue shell: real facility names, loud when the source file is missing or thin.
|
|
682
|
+
const venuePool = await readVenuePool(VENUE_POOL_CSV)
|
|
683
|
+
|
|
684
|
+
if (venuePool.length < 500) {
|
|
685
|
+
throw new Error(
|
|
686
|
+
`suffix-boundary v2 venue pool too thin: ${venuePool.length} names from ${VENUE_POOL_CSV} — ` +
|
|
687
|
+
"is the usgov-hrsa-fqhc source present?"
|
|
688
|
+
)
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const shell: RenderRowOpts = { venues: venuePool, cuts: [0.35, 0.55, 0.7] }
|
|
692
|
+
|
|
693
|
+
const pool: Record<SuffixBoundaryClass, USTuple[]> = {
|
|
694
|
+
"terminal-only": [],
|
|
695
|
+
"terminal-contrast": [],
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
for (const s of sources) {
|
|
699
|
+
for (const tuple of await readTuples(s)) {
|
|
700
|
+
const rowClass = classifySuffixBoundaryStreet(tuple.street)
|
|
701
|
+
|
|
702
|
+
if (rowClass) {
|
|
703
|
+
pool[rowClass].push(tuple)
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if (!pool["terminal-only"].length || !pool["terminal-contrast"].length) {
|
|
709
|
+
throw new Error(
|
|
710
|
+
`Suffix-boundary source class missing: terminal-only=${pool["terminal-only"].length}, ` +
|
|
711
|
+
`terminal-contrast=${pool["terminal-contrast"].length}`
|
|
712
|
+
)
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
let emitted = 0
|
|
716
|
+
let skipped = 0
|
|
717
|
+
const classCounts: Record<SuffixBoundaryClass, number> = { "terminal-only": 0, "terminal-contrast": 0 }
|
|
718
|
+
const terminalOnlyTarget = Math.round(count * 0.8)
|
|
719
|
+
|
|
720
|
+
const classTargets: Record<SuffixBoundaryClass, number> = {
|
|
721
|
+
"terminal-only": terminalOnlyTarget,
|
|
722
|
+
"terminal-contrast": count - terminalOnlyTarget,
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
const formatCounts: Record<string, number> = {}
|
|
726
|
+
let stemPairs = 0
|
|
727
|
+
|
|
728
|
+
const emitOne = (
|
|
729
|
+
rowClass: SuffixBoundaryClass,
|
|
730
|
+
base: USTuple,
|
|
731
|
+
parsed: NonNullable<ReturnType<typeof parseStreet>>,
|
|
732
|
+
method: string
|
|
733
|
+
): boolean => {
|
|
734
|
+
const { street, components: streetComponents } = renderStreet(random, parsed)
|
|
735
|
+
const { fmt, raw, components } = renderRow(random, base, street, streetComponents, shell)
|
|
736
|
+
|
|
737
|
+
const canonical: CanonicalRow = {
|
|
738
|
+
raw,
|
|
739
|
+
components,
|
|
740
|
+
country: "US",
|
|
741
|
+
locale: "en-US",
|
|
742
|
+
source,
|
|
743
|
+
source_id: shardSourceID(source, { ...components, class: rowClass, n: String(emitted) }),
|
|
744
|
+
corpus_version: "0.19.0",
|
|
745
|
+
license:
|
|
746
|
+
"OpenAddresses US (non-VT) skeletons; terminal suffix labels via USPS Pub-28 codex; venue shell from HRSA site names (US public domain)",
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
const aligned = alignRow(canonical)
|
|
750
|
+
|
|
751
|
+
if (aligned.kind !== "labeled" || !aligned.row) {
|
|
752
|
+
skipped++
|
|
753
|
+
|
|
754
|
+
return false
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
write(JSON.stringify({ ...aligned.row, synth_method: method, synth_base_id: base.base_source_id }) + "\n")
|
|
758
|
+
|
|
759
|
+
classCounts[rowClass]++
|
|
760
|
+
formatCounts[fmt] = (formatCounts[fmt] ?? 0) + 1
|
|
761
|
+
|
|
762
|
+
emitted++
|
|
763
|
+
|
|
764
|
+
return true
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// oxlint-disable-next-line eslint/no-unmodified-loop-condition -- emitted/skipped advance inside emitOne (a closure); the rule cannot see through the call
|
|
768
|
+
while (emitted < count && emitted + skipped < count * 10) {
|
|
769
|
+
const terminalOnlyOpen = classCounts["terminal-only"] < classTargets["terminal-only"]
|
|
770
|
+
const terminalContrastOpen = classCounts["terminal-contrast"] < classTargets["terminal-contrast"]
|
|
771
|
+
|
|
772
|
+
const rowClass: SuffixBoundaryClass =
|
|
773
|
+
terminalOnlyOpen && terminalContrastOpen
|
|
774
|
+
? random() < 0.8
|
|
775
|
+
? "terminal-only"
|
|
776
|
+
: "terminal-contrast"
|
|
777
|
+
: terminalContrastOpen
|
|
778
|
+
? "terminal-contrast"
|
|
779
|
+
: "terminal-only"
|
|
780
|
+
|
|
781
|
+
const classPool = pool[rowClass]
|
|
782
|
+
const base = classPool[Math.floor(random() * classPool.length)]!
|
|
783
|
+
const parsed = parseStreet(base.street, { allowNameProneTail: rowClass === "terminal-only" })
|
|
784
|
+
|
|
785
|
+
if (!parsed) {
|
|
786
|
+
skipped++
|
|
787
|
+
|
|
788
|
+
continue
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
if (!emitOne(rowClass, base, parsed, `suffix-boundary:${rowClass}`)) continue
|
|
792
|
+
|
|
793
|
+
// Stem-pair hard negative (v2, 2026-08-10 recipe review): after a terminal-only row
|
|
794
|
+
// ('Menlo Park' + 'Road'), also emit the SAME stem without its true suffix as a
|
|
795
|
+
// contrast row ('Menlo' + 'Park' under the canonical last-token rule). Sharing the stem
|
|
796
|
+
// forces the model to key on the licensing evidence — the trailing true suffix — rather
|
|
797
|
+
// than on name identity. Dose-neutral: these fill the existing 20% contrast target.
|
|
798
|
+
if (
|
|
799
|
+
rowClass === "terminal-only" &&
|
|
800
|
+
classCounts["terminal-contrast"] < classTargets["terminal-contrast"] &&
|
|
801
|
+
emitted < count &&
|
|
802
|
+
random() < 0.5
|
|
803
|
+
) {
|
|
804
|
+
const stemParsed = parseStreet(parsed.name)
|
|
805
|
+
|
|
806
|
+
if (
|
|
807
|
+
stemParsed &&
|
|
808
|
+
emitOne("terminal-contrast", base, stemParsed, "suffix-boundary:terminal-contrast:stem-pair")
|
|
809
|
+
) {
|
|
810
|
+
stemPairs++
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
console.error(
|
|
816
|
+
`Done: emitted ${emitted}, skipped ${skipped}; source pools ${JSON.stringify({
|
|
817
|
+
terminalOnly: pool["terminal-only"].length,
|
|
818
|
+
terminalContrast: pool["terminal-contrast"].length,
|
|
819
|
+
})}; classes ${JSON.stringify(classCounts)}; stem pairs ${stemPairs}; ` +
|
|
820
|
+
`venue pool ${venuePool.length}; formats ${JSON.stringify(formatCounts)}`
|
|
821
|
+
)
|
|
822
|
+
|
|
823
|
+
return { emitted, skipped }
|
|
824
|
+
},
|
|
825
|
+
}
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
* reproduces the legacy run byte-for-byte.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
20
|
+
import { DEFAULT_US_BASES } from "@mailwoman/corpus/synthesizers/intersection"
|
|
21
|
+
import { synthesizeStreetRow, type StreetBaseTuple } from "@mailwoman/corpus/synthesizers/street"
|
|
22
|
+
import { alignRow } from "@mailwoman/corpus/utils"
|
|
23
|
+
|
|
23
24
|
import { makeMulberry32, shardSourceID, type CanonicalShardRow, type ShardRecipe } from "./scaffold.ts"
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* {@link synthesizeStreetRow} → aligned LabeledRow. Ported from scripts/build-street-shard.mjs.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { stableSourceID } from "
|
|
11
|
-
import { synthesizeStreetRow, type StreetBaseTuple } from "
|
|
10
|
+
import { stableSourceID } from "@mailwoman/corpus/adapters/utils"
|
|
11
|
+
import { synthesizeStreetRow, type StreetBaseTuple } from "@mailwoman/corpus/synthesizers/street"
|
|
12
|
+
|
|
12
13
|
import { alignAndWrite, makeLcg, readTuples, type ShardRecipe } from "./scaffold.ts"
|
|
13
14
|
|
|
14
15
|
/**
|