@mailwoman/corpus 9.0.0 → 9.2.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.
Files changed (524) hide show
  1. package/README.md +3 -3
  2. package/data/PROVENANCE.md +227 -0
  3. package/data/reviewed-ve-postcode-tuples.json +74 -0
  4. package/data/sub-venue-lexicon.json +18269 -0
  5. package/out/src/adapters/ban/adapter.d.ts +1 -1
  6. package/out/src/adapters/ban/adapter.d.ts.map +1 -1
  7. package/out/src/adapters/ban/adapter.js +5 -4
  8. package/out/src/adapters/ban/adapter.js.map +1 -1
  9. package/out/src/adapters/fcc-bdc/adapter.d.ts +1 -1
  10. package/out/src/adapters/fcc-bdc/adapter.d.ts.map +1 -1
  11. package/out/src/adapters/fcc-bdc/adapter.js +3 -3
  12. package/out/src/adapters/fcc-bdc/adapter.js.map +1 -1
  13. package/out/src/adapters/geonames/adapter.d.ts +1 -1
  14. package/out/src/adapters/geonames/adapter.d.ts.map +1 -1
  15. package/out/src/adapters/geonames/adapter.js +2 -2
  16. package/out/src/adapters/geonames/adapter.js.map +1 -1
  17. package/out/src/adapters/geonames-postal/adapter.d.ts +1 -1
  18. package/out/src/adapters/geonames-postal/adapter.d.ts.map +1 -1
  19. package/out/src/adapters/geonames-postal/adapter.js +3 -3
  20. package/out/src/adapters/geonames-postal/adapter.js.map +1 -1
  21. package/out/src/adapters/gnaf/adapter.d.ts +1 -1
  22. package/out/src/adapters/gnaf/adapter.d.ts.map +1 -1
  23. package/out/src/adapters/gnaf/adapter.js +2 -2
  24. package/out/src/adapters/gnaf/adapter.js.map +1 -1
  25. package/out/src/adapters/gnaf/assemble.js +1 -1
  26. package/out/src/adapters/gnaf/assemble.js.map +1 -1
  27. package/out/src/adapters/index.d.ts +1 -1
  28. package/out/src/adapters/index.d.ts.map +1 -1
  29. package/out/src/adapters/index.js +1 -1
  30. package/out/src/adapters/index.js.map +1 -1
  31. package/out/src/adapters/openaddresses/adapter.d.ts +1 -1
  32. package/out/src/adapters/openaddresses/adapter.d.ts.map +1 -1
  33. package/out/src/adapters/openaddresses/adapter.js +3 -3
  34. package/out/src/adapters/openaddresses/adapter.js.map +1 -1
  35. package/out/src/adapters/overture/adapter.d.ts +1 -1
  36. package/out/src/adapters/overture/adapter.d.ts.map +1 -1
  37. package/out/src/adapters/overture/adapter.js +2 -2
  38. package/out/src/adapters/overture/adapter.js.map +1 -1
  39. package/out/src/adapters/state-hi-schools/adapter.d.ts +1 -1
  40. package/out/src/adapters/state-hi-schools/adapter.d.ts.map +1 -1
  41. package/out/src/adapters/state-hi-schools/adapter.js +7 -6
  42. package/out/src/adapters/state-hi-schools/adapter.js.map +1 -1
  43. package/out/src/adapters/state-ia-contractors/adapter.d.ts +1 -1
  44. package/out/src/adapters/state-ia-contractors/adapter.d.ts.map +1 -1
  45. package/out/src/adapters/state-ia-contractors/adapter.js +12 -7
  46. package/out/src/adapters/state-ia-contractors/adapter.js.map +1 -1
  47. package/out/src/adapters/state-ny-notaries/adapter.d.ts +1 -1
  48. package/out/src/adapters/state-ny-notaries/adapter.d.ts.map +1 -1
  49. package/out/src/adapters/state-ny-notaries/adapter.js +12 -18
  50. package/out/src/adapters/state-ny-notaries/adapter.js.map +1 -1
  51. package/out/src/adapters/state-tx-notaries/adapter.d.ts +1 -1
  52. package/out/src/adapters/state-tx-notaries/adapter.d.ts.map +1 -1
  53. package/out/src/adapters/state-tx-notaries/adapter.js +12 -7
  54. package/out/src/adapters/state-tx-notaries/adapter.js.map +1 -1
  55. package/out/src/adapters/synth-po-box/adapter.d.ts +3 -3
  56. package/out/src/adapters/synth-po-box/adapter.d.ts.map +1 -1
  57. package/out/src/adapters/synth-po-box/adapter.js +3 -3
  58. package/out/src/adapters/synth-po-box/adapter.js.map +1 -1
  59. package/out/src/adapters/tiger/adapter.d.ts +1 -1
  60. package/out/src/adapters/tiger/adapter.d.ts.map +1 -1
  61. package/out/src/adapters/tiger/adapter.js +2 -2
  62. package/out/src/adapters/tiger/adapter.js.map +1 -1
  63. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +1 -1
  64. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts.map +1 -1
  65. package/out/src/adapters/usgov-hrsa-fqhc/adapter.js +7 -6
  66. package/out/src/adapters/usgov-hrsa-fqhc/adapter.js.map +1 -1
  67. package/out/src/adapters/usgov-imls-pls/adapter.d.ts +1 -1
  68. package/out/src/adapters/usgov-imls-pls/adapter.d.ts.map +1 -1
  69. package/out/src/adapters/usgov-imls-pls/adapter.js +11 -7
  70. package/out/src/adapters/usgov-imls-pls/adapter.js.map +1 -1
  71. package/out/src/adapters/usgov-irs-bmf/adapter.d.ts +1 -1
  72. package/out/src/adapters/usgov-irs-bmf/adapter.d.ts.map +1 -1
  73. package/out/src/adapters/usgov-irs-bmf/adapter.js +6 -5
  74. package/out/src/adapters/usgov-irs-bmf/adapter.js.map +1 -1
  75. package/out/src/adapters/usgov-nad/adapter.d.ts +1 -1
  76. package/out/src/adapters/usgov-nad/adapter.d.ts.map +1 -1
  77. package/out/src/adapters/usgov-nad/adapter.js +8 -8
  78. package/out/src/adapters/usgov-nad/adapter.js.map +1 -1
  79. package/out/src/adapters/usgov-nppes/adapter.d.ts +1 -1
  80. package/out/src/adapters/usgov-nppes/adapter.d.ts.map +1 -1
  81. package/out/src/adapters/usgov-nppes/adapter.js +10 -10
  82. package/out/src/adapters/usgov-nppes/adapter.js.map +1 -1
  83. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts +1 -1
  84. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts.map +1 -1
  85. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js +7 -6
  86. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js.map +1 -1
  87. package/out/src/{adapter.d.ts → adapters/utils/index.d.ts} +8 -2
  88. package/out/src/adapters/utils/index.d.ts.map +1 -0
  89. package/out/src/{adapter.js → adapters/utils/index.js} +11 -3
  90. package/out/src/adapters/utils/index.js.map +1 -0
  91. package/out/src/adapters/wof-admin-jp/adapter.d.ts +1 -1
  92. package/out/src/adapters/wof-admin-jp/adapter.d.ts.map +1 -1
  93. package/out/src/adapters/wof-admin-jp/adapter.js +5 -5
  94. package/out/src/adapters/wof-admin-jp/adapter.js.map +1 -1
  95. package/out/src/adapters/wof-admin-json/adapter.d.ts +4 -15
  96. package/out/src/adapters/wof-admin-json/adapter.d.ts.map +1 -1
  97. package/out/src/adapters/wof-admin-json/adapter.js +11 -35
  98. package/out/src/adapters/wof-admin-json/adapter.js.map +1 -1
  99. package/out/src/adapters/wof-json-rows.d.ts +32 -0
  100. package/out/src/adapters/wof-json-rows.d.ts.map +1 -0
  101. package/out/src/adapters/wof-json-rows.js +45 -0
  102. package/out/src/adapters/wof-json-rows.js.map +1 -0
  103. package/out/src/adapters/wof-postalcode-json/adapter.d.ts +4 -9
  104. package/out/src/adapters/wof-postalcode-json/adapter.d.ts.map +1 -1
  105. package/out/src/adapters/wof-postalcode-json/adapter.js +12 -37
  106. package/out/src/adapters/wof-postalcode-json/adapter.js.map +1 -1
  107. package/out/src/build.d.ts +4 -4
  108. package/out/src/build.d.ts.map +1 -1
  109. package/out/src/build.js +7 -7
  110. package/out/src/build.js.map +1 -1
  111. package/out/src/index.d.ts +3 -17
  112. package/out/src/index.d.ts.map +1 -1
  113. package/out/src/index.js +3 -17
  114. package/out/src/index.js.map +1 -1
  115. package/out/src/name-prone-us-suffixes.d.ts +12 -0
  116. package/out/src/name-prone-us-suffixes.d.ts.map +1 -0
  117. package/out/src/name-prone-us-suffixes.js +12 -0
  118. package/out/src/name-prone-us-suffixes.js.map +1 -0
  119. package/out/src/parquet-wrapper/reader.d.ts.map +1 -1
  120. package/out/src/parquet-wrapper/reader.js +5 -0
  121. package/out/src/parquet-wrapper/reader.js.map +1 -1
  122. package/out/src/runner.d.ts +2 -2
  123. package/out/src/runner.d.ts.map +1 -1
  124. package/out/src/runner.js +1 -1
  125. package/out/src/runner.js.map +1 -1
  126. package/out/src/shard-recipes/anchor-absorption.d.ts.map +1 -1
  127. package/out/src/shard-recipes/anchor-absorption.js +4 -5
  128. package/out/src/shard-recipes/anchor-absorption.js.map +1 -1
  129. package/out/src/shard-recipes/bare-country.d.ts +25 -0
  130. package/out/src/shard-recipes/bare-country.d.ts.map +1 -0
  131. package/out/src/shard-recipes/bare-country.js +87 -0
  132. package/out/src/shard-recipes/bare-country.js.map +1 -0
  133. package/out/src/shard-recipes/boundary-stress.d.ts.map +1 -1
  134. package/out/src/shard-recipes/boundary-stress.js +2 -2
  135. package/out/src/shard-recipes/boundary-stress.js.map +1 -1
  136. package/out/src/shard-recipes/country-balanced.d.ts.map +1 -1
  137. package/out/src/shard-recipes/country-balanced.js +14 -21
  138. package/out/src/shard-recipes/country-balanced.js.map +1 -1
  139. package/out/src/shard-recipes/cz-pcfirst-preposition.d.ts.map +1 -1
  140. package/out/src/shard-recipes/cz-pcfirst-preposition.js +28 -10
  141. package/out/src/shard-recipes/cz-pcfirst-preposition.js.map +1 -1
  142. package/out/src/shard-recipes/fr-admin-split.d.ts.map +1 -1
  143. package/out/src/shard-recipes/fr-admin-split.js +4 -3
  144. package/out/src/shard-recipes/fr-admin-split.js.map +1 -1
  145. package/out/src/shard-recipes/fr-bare-street.d.ts.map +1 -1
  146. package/out/src/shard-recipes/fr-bare-street.js +72 -11
  147. package/out/src/shard-recipes/fr-bare-street.js.map +1 -1
  148. package/out/src/shard-recipes/fr-lieudit.d.ts.map +1 -1
  149. package/out/src/shard-recipes/fr-lieudit.js +4 -3
  150. package/out/src/shard-recipes/fr-lieudit.js.map +1 -1
  151. package/out/src/shard-recipes/fr-order.d.ts.map +1 -1
  152. package/out/src/shard-recipes/fr-order.js +11 -20
  153. package/out/src/shard-recipes/fr-order.js.map +1 -1
  154. package/out/src/shard-recipes/german.d.ts.map +1 -1
  155. package/out/src/shard-recipes/german.js +8 -14
  156. package/out/src/shard-recipes/german.js.map +1 -1
  157. package/out/src/shard-recipes/house-venue.d.ts.map +1 -1
  158. package/out/src/shard-recipes/house-venue.js +1 -1
  159. package/out/src/shard-recipes/house-venue.js.map +1 -1
  160. package/out/src/shard-recipes/index.d.ts.map +1 -1
  161. package/out/src/shard-recipes/index.js +8 -1
  162. package/out/src/shard-recipes/index.js.map +1 -1
  163. package/out/src/shard-recipes/intersection.d.ts.map +1 -1
  164. package/out/src/shard-recipes/intersection.js +7 -13
  165. package/out/src/shard-recipes/intersection.js.map +1 -1
  166. package/out/src/shard-recipes/locale.d.ts +5 -5
  167. package/out/src/shard-recipes/locale.d.ts.map +1 -1
  168. package/out/src/shard-recipes/locale.js +13 -20
  169. package/out/src/shard-recipes/locale.js.map +1 -1
  170. package/out/src/shard-recipes/no-street.d.ts.map +1 -1
  171. package/out/src/shard-recipes/no-street.js +1 -1
  172. package/out/src/shard-recipes/no-street.js.map +1 -1
  173. package/out/src/shard-recipes/po-box-cedex.d.ts.map +1 -1
  174. package/out/src/shard-recipes/po-box-cedex.js +60 -43
  175. package/out/src/shard-recipes/po-box-cedex.js.map +1 -1
  176. package/out/src/shard-recipes/po-box.d.ts.map +1 -1
  177. package/out/src/shard-recipes/po-box.js +1 -1
  178. package/out/src/shard-recipes/po-box.js.map +1 -1
  179. package/out/src/shard-recipes/reviewed-postcode-tail.d.ts +47 -0
  180. package/out/src/shard-recipes/reviewed-postcode-tail.d.ts.map +1 -0
  181. package/out/src/shard-recipes/reviewed-postcode-tail.js +125 -0
  182. package/out/src/shard-recipes/reviewed-postcode-tail.js.map +1 -0
  183. package/out/src/shard-recipes/scaffold.d.ts +51 -23
  184. package/out/src/shard-recipes/scaffold.d.ts.map +1 -1
  185. package/out/src/shard-recipes/scaffold.js +59 -23
  186. package/out/src/shard-recipes/scaffold.js.map +1 -1
  187. package/out/src/shard-recipes/street-affix.d.ts +54 -0
  188. package/out/src/shard-recipes/street-affix.d.ts.map +1 -1
  189. package/out/src/shard-recipes/street-affix.js +203 -35
  190. package/out/src/shard-recipes/street-affix.js.map +1 -1
  191. package/out/src/shard-recipes/street-bare.d.ts.map +1 -1
  192. package/out/src/shard-recipes/street-bare.js +3 -3
  193. package/out/src/shard-recipes/street-bare.js.map +1 -1
  194. package/out/src/shard-recipes/street.d.ts.map +1 -1
  195. package/out/src/shard-recipes/street.js +2 -2
  196. package/out/src/shard-recipes/street.js.map +1 -1
  197. package/out/src/shard-recipes/sub-venue-sources.d.ts +3 -6
  198. package/out/src/shard-recipes/sub-venue-sources.d.ts.map +1 -1
  199. package/out/src/shard-recipes/sub-venue-sources.js +4 -9
  200. package/out/src/shard-recipes/sub-venue-sources.js.map +1 -1
  201. package/out/src/shard-recipes/sub-venue.d.ts +2 -2
  202. package/out/src/shard-recipes/sub-venue.d.ts.map +1 -1
  203. package/out/src/shard-recipes/sub-venue.js +7 -6
  204. package/out/src/shard-recipes/sub-venue.js.map +1 -1
  205. package/out/src/shard-recipes/trailing-region.d.ts +74 -0
  206. package/out/src/shard-recipes/trailing-region.d.ts.map +1 -0
  207. package/out/src/shard-recipes/trailing-region.js +157 -0
  208. package/out/src/shard-recipes/trailing-region.js.map +1 -0
  209. package/out/src/shard-recipes/unit.d.ts.map +1 -1
  210. package/out/src/shard-recipes/unit.js +6 -12
  211. package/out/src/shard-recipes/unit.js.map +1 -1
  212. package/out/src/{synthesize-anchor-absorption.d.ts → synthesizers/anchor-absorption.d.ts} +1 -1
  213. package/out/src/synthesizers/anchor-absorption.d.ts.map +1 -0
  214. package/out/src/{synthesize-anchor-absorption.js → synthesizers/anchor-absorption.js} +1 -1
  215. package/out/src/synthesizers/anchor-absorption.js.map +1 -0
  216. package/out/src/{synthesize-boundary-stress.d.ts → synthesizers/boundary-stress.d.ts} +3 -3
  217. package/out/src/synthesizers/boundary-stress.d.ts.map +1 -0
  218. package/out/src/{synthesize-boundary-stress.js → synthesizers/boundary-stress.js} +2 -2
  219. package/out/src/synthesizers/boundary-stress.js.map +1 -0
  220. package/out/src/{synthesize-german.d.ts → synthesizers/german.d.ts} +2 -2
  221. package/out/src/synthesizers/german.d.ts.map +1 -0
  222. package/out/src/{synthesize-german.js → synthesizers/german.js} +2 -2
  223. package/out/src/synthesizers/german.js.map +1 -0
  224. package/out/src/{synthesize-house-venue.d.ts → synthesizers/house-venue.d.ts} +4 -4
  225. package/out/src/synthesizers/house-venue.d.ts.map +1 -0
  226. package/out/src/{synthesize-house-venue.js → synthesizers/house-venue.js} +20 -6
  227. package/out/src/synthesizers/house-venue.js.map +1 -0
  228. package/out/src/{synthesize-intersection.d.ts → synthesizers/intersection.d.ts} +2 -2
  229. package/out/src/synthesizers/intersection.d.ts.map +1 -0
  230. package/out/src/{synthesize-intersection.js → synthesizers/intersection.js} +1 -1
  231. package/out/src/synthesizers/intersection.js.map +1 -0
  232. package/out/src/{synthesize-no-street.d.ts → synthesizers/no-street.d.ts} +3 -3
  233. package/out/src/synthesizers/no-street.d.ts.map +1 -0
  234. package/out/src/{synthesize-no-street.js → synthesizers/no-street.js} +2 -2
  235. package/out/src/synthesizers/no-street.js.map +1 -0
  236. package/out/src/{synthesize-po-box.d.ts → synthesizers/po-box.d.ts} +2 -2
  237. package/out/src/synthesizers/po-box.d.ts.map +1 -0
  238. package/out/src/{synthesize-po-box.js → synthesizers/po-box.js} +1 -1
  239. package/out/src/synthesizers/po-box.js.map +1 -0
  240. package/out/src/{synthesize-street.d.ts → synthesizers/street.d.ts} +2 -2
  241. package/out/src/synthesizers/street.d.ts.map +1 -0
  242. package/out/src/{synthesize-street.js → synthesizers/street.js} +4 -3
  243. package/out/src/synthesizers/street.js.map +1 -0
  244. package/out/src/{synthesize.d.ts → synthesizers/utils.d.ts} +3 -3
  245. package/out/src/synthesizers/utils.d.ts.map +1 -0
  246. package/out/src/{synthesize.js → synthesizers/utils.js} +5 -4
  247. package/out/src/synthesizers/utils.js.map +1 -0
  248. package/out/src/tools/align-shard.d.ts.map +1 -1
  249. package/out/src/tools/align-shard.js +2 -2
  250. package/out/src/tools/align-shard.js.map +1 -1
  251. package/out/src/tools/fetch/ban.d.ts.map +1 -1
  252. package/out/src/tools/fetch/ban.js +2 -18
  253. package/out/src/tools/fetch/ban.js.map +1 -1
  254. package/out/src/tools/fetch/download.d.ts +12 -3
  255. package/out/src/tools/fetch/download.d.ts.map +1 -1
  256. package/out/src/tools/fetch/download.js +20 -4
  257. package/out/src/tools/fetch/download.js.map +1 -1
  258. package/out/src/tools/fetch/geonames-dump.d.ts +87 -0
  259. package/out/src/tools/fetch/geonames-dump.d.ts.map +1 -0
  260. package/out/src/tools/fetch/geonames-dump.js +178 -0
  261. package/out/src/tools/fetch/geonames-dump.js.map +1 -0
  262. package/out/src/tools/fetch/geonames-postal.d.ts +76 -0
  263. package/out/src/tools/fetch/geonames-postal.d.ts.map +1 -0
  264. package/out/src/tools/fetch/geonames-postal.js +125 -0
  265. package/out/src/tools/fetch/geonames-postal.js.map +1 -0
  266. package/out/src/tools/fetch/imls-pls.d.ts.map +1 -1
  267. package/out/src/tools/fetch/imls-pls.js +5 -17
  268. package/out/src/tools/fetch/imls-pls.js.map +1 -1
  269. package/out/src/tools/fetch/index.d.ts +11 -0
  270. package/out/src/tools/fetch/index.d.ts.map +1 -1
  271. package/out/src/tools/fetch/index.js +11 -0
  272. package/out/src/tools/fetch/index.js.map +1 -1
  273. package/out/src/tools/fetch/nad.d.ts.map +1 -1
  274. package/out/src/tools/fetch/nad.js +20 -11
  275. package/out/src/tools/fetch/nad.js.map +1 -1
  276. package/out/src/tools/fetch/nppes.d.ts.map +1 -1
  277. package/out/src/tools/fetch/nppes.js +17 -22
  278. package/out/src/tools/fetch/nppes.js.map +1 -1
  279. package/out/src/tools/fetch/openaddresses.d.ts.map +1 -1
  280. package/out/src/tools/fetch/openaddresses.js +18 -17
  281. package/out/src/tools/fetch/openaddresses.js.map +1 -1
  282. package/out/src/tools/fetch/ourairports.d.ts.map +1 -1
  283. package/out/src/tools/fetch/ourairports.js +7 -2
  284. package/out/src/tools/fetch/ourairports.js.map +1 -1
  285. package/out/src/tools/fetch/ppd.d.ts +0 -4
  286. package/out/src/tools/fetch/ppd.d.ts.map +1 -1
  287. package/out/src/tools/fetch/ppd.js +1 -1
  288. package/out/src/tools/fetch/ppd.js.map +1 -1
  289. package/out/src/tools/fetch/state-hi-schools.d.ts.map +1 -1
  290. package/out/src/tools/fetch/state-hi-schools.js +3 -19
  291. package/out/src/tools/fetch/state-hi-schools.js.map +1 -1
  292. package/out/src/tools/fetch/state-sources.d.ts +4 -0
  293. package/out/src/tools/fetch/state-sources.d.ts.map +1 -1
  294. package/out/src/tools/fetch/state-sources.js +1 -5
  295. package/out/src/tools/fetch/state-sources.js.map +1 -1
  296. package/out/src/tools/fetch/tiger-full.d.ts.map +1 -1
  297. package/out/src/tools/fetch/tiger-full.js +15 -21
  298. package/out/src/tools/fetch/tiger-full.js.map +1 -1
  299. package/out/src/tools/golden-expand.d.ts.map +1 -1
  300. package/out/src/tools/golden-expand.js +34 -25
  301. package/out/src/tools/golden-expand.js.map +1 -1
  302. package/out/src/tools/golden-relabel-street.d.ts.map +1 -1
  303. package/out/src/tools/golden-relabel-street.js +4 -77
  304. package/out/src/tools/golden-relabel-street.js.map +1 -1
  305. package/out/src/tools/index.d.ts +2 -2
  306. package/out/src/tools/index.d.ts.map +1 -1
  307. package/out/src/tools/index.js +2 -2
  308. package/out/src/tools/index.js.map +1 -1
  309. package/out/src/tools/ingest-csv.d.ts.map +1 -1
  310. package/out/src/tools/ingest-csv.js +0 -11
  311. package/out/src/tools/ingest-csv.js.map +1 -1
  312. package/out/src/tools/overlay-manifest.d.ts +4 -0
  313. package/out/src/tools/overlay-manifest.d.ts.map +1 -1
  314. package/out/src/tools/overlay-manifest.js +16 -6
  315. package/out/src/tools/overlay-manifest.js.map +1 -1
  316. package/out/src/tools/postcode-triples.d.ts +175 -0
  317. package/out/src/tools/postcode-triples.d.ts.map +1 -0
  318. package/out/src/tools/postcode-triples.js +304 -0
  319. package/out/src/tools/postcode-triples.js.map +1 -0
  320. package/out/src/tools/shard-kryptonite.d.ts.map +1 -1
  321. package/out/src/tools/shard-kryptonite.js +1 -3
  322. package/out/src/tools/shard-kryptonite.js.map +1 -1
  323. package/out/src/tools/shard-translit.d.ts.map +1 -1
  324. package/out/src/tools/shard-translit.js +4 -27
  325. package/out/src/tools/shard-translit.js.map +1 -1
  326. package/out/src/tools/sub-venue/harvest.d.ts +100 -0
  327. package/out/src/tools/sub-venue/harvest.d.ts.map +1 -0
  328. package/out/src/tools/sub-venue/harvest.js +168 -0
  329. package/out/src/tools/sub-venue/harvest.js.map +1 -0
  330. package/out/src/tools/sub-venue/head-nouns.d.ts +50 -0
  331. package/out/src/tools/sub-venue/head-nouns.d.ts.map +1 -0
  332. package/out/src/tools/sub-venue/head-nouns.js +210 -0
  333. package/out/src/tools/sub-venue/head-nouns.js.map +1 -0
  334. package/out/src/tools/sub-venue/surfaces.d.ts +45 -0
  335. package/out/src/tools/sub-venue/surfaces.d.ts.map +1 -0
  336. package/out/src/tools/sub-venue/surfaces.js +77 -0
  337. package/out/src/tools/sub-venue/surfaces.js.map +1 -0
  338. package/out/src/tools/sub-venue/table.d.ts +229 -0
  339. package/out/src/tools/sub-venue/table.d.ts.map +1 -0
  340. package/out/src/tools/sub-venue/table.js +108 -0
  341. package/out/src/tools/sub-venue/table.js.map +1 -0
  342. package/out/src/tools/sub-venue/wikidata.d.ts +26 -0
  343. package/out/src/tools/sub-venue/wikidata.d.ts.map +1 -0
  344. package/out/src/tools/sub-venue/wikidata.js +62 -0
  345. package/out/src/tools/sub-venue/wikidata.js.map +1 -0
  346. package/out/src/tools/sub-venue-lexicon.d.ts +27 -378
  347. package/out/src/tools/sub-venue-lexicon.d.ts.map +1 -1
  348. package/out/src/tools/sub-venue-lexicon.js +30 -565
  349. package/out/src/tools/sub-venue-lexicon.js.map +1 -1
  350. package/out/src/{align.d.ts → utils/align.d.ts} +1 -1
  351. package/out/src/utils/align.d.ts.map +1 -0
  352. package/out/src/utils/align.js.map +1 -0
  353. package/out/src/utils/golden.d.ts.map +1 -0
  354. package/out/src/{golden.js → utils/golden.js} +2 -2
  355. package/out/src/utils/golden.js.map +1 -0
  356. package/out/src/utils/index.d.ts +14 -0
  357. package/out/src/utils/index.d.ts.map +1 -0
  358. package/out/src/utils/index.js +14 -0
  359. package/out/src/utils/index.js.map +1 -0
  360. package/out/src/utils/license.d.ts.map +1 -0
  361. package/out/src/{license.js → utils/license.js} +1 -1
  362. package/out/src/utils/license.js.map +1 -0
  363. package/out/src/{parquet.d.ts → utils/parquet.d.ts} +24 -5
  364. package/out/src/utils/parquet.d.ts.map +1 -0
  365. package/out/src/{parquet.js → utils/parquet.js} +6 -3
  366. package/out/src/utils/parquet.js.map +1 -0
  367. package/out/src/{split.d.ts → utils/split.d.ts} +1 -1
  368. package/out/src/utils/split.d.ts.map +1 -0
  369. package/out/src/{split.js → utils/split.js} +2 -2
  370. package/out/src/utils/split.js.map +1 -0
  371. package/out/src/utils/tokenize.d.ts.map +1 -0
  372. package/out/src/utils/tokenize.js.map +1 -0
  373. package/out/src/utils/wof-json.d.ts.map +1 -0
  374. package/out/src/utils/wof-json.js.map +1 -0
  375. package/package.json +287 -21
  376. package/src/adapters/ban/adapter.ts +7 -5
  377. package/src/adapters/fcc-bdc/adapter.ts +5 -4
  378. package/src/adapters/geonames/adapter.ts +3 -3
  379. package/src/adapters/geonames-postal/adapter.ts +4 -4
  380. package/src/adapters/gnaf/adapter.ts +3 -3
  381. package/src/adapters/gnaf/assemble.ts +1 -1
  382. package/src/adapters/index.ts +3 -2
  383. package/src/adapters/openaddresses/adapter.ts +4 -4
  384. package/src/adapters/overture/adapter.ts +3 -3
  385. package/src/adapters/state-hi-schools/adapter.ts +8 -7
  386. package/src/adapters/state-ia-contractors/adapter.ts +13 -8
  387. package/src/adapters/state-ny-notaries/adapter.ts +13 -32
  388. package/src/adapters/state-tx-notaries/adapter.ts +13 -8
  389. package/src/adapters/synth-po-box/adapter.ts +4 -4
  390. package/src/adapters/tiger/adapter.ts +5 -3
  391. package/src/adapters/usgov-hrsa-fqhc/adapter.ts +8 -7
  392. package/src/adapters/usgov-imls-pls/adapter.ts +12 -8
  393. package/src/adapters/usgov-irs-bmf/adapter.ts +7 -6
  394. package/src/adapters/usgov-nad/adapter.ts +9 -9
  395. package/src/adapters/usgov-nppes/adapter.ts +13 -12
  396. package/src/adapters/usgov-samhsa-treatment-locator/adapter.ts +8 -7
  397. package/src/{adapter.ts → adapters/utils/index.ts} +15 -3
  398. package/src/adapters/wof-admin-jp/adapter.ts +9 -12
  399. package/src/adapters/wof-admin-json/adapter.ts +15 -54
  400. package/src/adapters/wof-json-rows.ts +79 -0
  401. package/src/adapters/wof-postalcode-json/adapter.ts +16 -50
  402. package/src/build.ts +8 -8
  403. package/src/index.ts +3 -17
  404. package/src/name-prone-us-suffixes.ts +12 -0
  405. package/src/parquet-wrapper/reader.ts +9 -0
  406. package/src/runner.ts +2 -2
  407. package/src/shard-recipes/anchor-absorption.ts +5 -5
  408. package/src/shard-recipes/bare-country.ts +95 -0
  409. package/src/shard-recipes/boundary-stress.ts +3 -2
  410. package/src/shard-recipes/country-balanced.ts +16 -27
  411. package/src/shard-recipes/cz-pcfirst-preposition.ts +29 -10
  412. package/src/shard-recipes/fr-admin-split.ts +6 -4
  413. package/src/shard-recipes/fr-bare-street.ts +85 -10
  414. package/src/shard-recipes/fr-lieudit.ts +6 -4
  415. package/src/shard-recipes/fr-order.ts +13 -26
  416. package/src/shard-recipes/german.ts +9 -18
  417. package/src/shard-recipes/house-venue.ts +2 -1
  418. package/src/shard-recipes/index.ts +8 -1
  419. package/src/shard-recipes/intersection.ts +9 -17
  420. package/src/shard-recipes/locale.ts +16 -24
  421. package/src/shard-recipes/no-street.ts +2 -1
  422. package/src/shard-recipes/po-box-cedex.ts +76 -58
  423. package/src/shard-recipes/po-box.ts +2 -1
  424. package/src/shard-recipes/reviewed-postcode-tail.ts +189 -0
  425. package/src/shard-recipes/scaffold.ts +99 -24
  426. package/src/shard-recipes/street-affix.ts +284 -45
  427. package/src/shard-recipes/street-bare.ts +4 -3
  428. package/src/shard-recipes/street.ts +3 -2
  429. package/src/shard-recipes/sub-venue-sources.ts +13 -23
  430. package/src/shard-recipes/sub-venue.ts +11 -9
  431. package/src/shard-recipes/trailing-region.ts +183 -0
  432. package/src/shard-recipes/unit.ts +8 -17
  433. package/src/{synthesize-boundary-stress.ts → synthesizers/boundary-stress.ts} +2 -2
  434. package/src/{synthesize-german.ts → synthesizers/german.ts} +3 -2
  435. package/src/{synthesize-house-venue.ts → synthesizers/house-venue.ts} +20 -6
  436. package/src/{synthesize-intersection.ts → synthesizers/intersection.ts} +1 -1
  437. package/src/{synthesize-no-street.ts → synthesizers/no-street.ts} +2 -2
  438. package/src/{synthesize-po-box.ts → synthesizers/po-box.ts} +1 -1
  439. package/src/{synthesize-street.ts → synthesizers/street.ts} +5 -3
  440. package/src/{synthesize.ts → synthesizers/utils.ts} +6 -4
  441. package/src/tools/align-shard.ts +3 -2
  442. package/src/tools/fetch/ban.ts +2 -22
  443. package/src/tools/fetch/download.ts +22 -4
  444. package/src/tools/fetch/geonames-dump.ts +267 -0
  445. package/src/tools/fetch/geonames-postal.ts +180 -0
  446. package/src/tools/fetch/imls-pls.ts +6 -20
  447. package/src/tools/fetch/index.ts +11 -0
  448. package/src/tools/fetch/nad.ts +21 -10
  449. package/src/tools/fetch/nppes.ts +17 -23
  450. package/src/tools/fetch/openaddresses.ts +18 -22
  451. package/src/tools/fetch/ourairports.ts +7 -2
  452. package/src/tools/fetch/ppd.ts +1 -1
  453. package/src/tools/fetch/state-hi-schools.ts +3 -23
  454. package/src/tools/fetch/state-sources.ts +1 -1
  455. package/src/tools/fetch/tiger-full.ts +17 -24
  456. package/src/tools/golden-expand.ts +44 -33
  457. package/src/tools/golden-relabel-street.ts +5 -68
  458. package/src/tools/index.ts +2 -2
  459. package/src/tools/ingest-csv.ts +0 -13
  460. package/src/tools/overlay-manifest.ts +20 -8
  461. package/src/tools/postcode-triples.ts +375 -0
  462. package/src/tools/shard-kryptonite.ts +4 -5
  463. package/src/tools/shard-translit.ts +16 -35
  464. package/src/tools/sub-venue/harvest.ts +235 -0
  465. package/src/tools/sub-venue/head-nouns.ts +242 -0
  466. package/src/tools/sub-venue/surfaces.ts +95 -0
  467. package/src/tools/sub-venue/table.ts +281 -0
  468. package/src/tools/sub-venue/wikidata.ts +85 -0
  469. package/src/tools/sub-venue-lexicon.ts +67 -886
  470. package/src/{align.ts → utils/align.ts} +2 -1
  471. package/src/{golden.ts → utils/golden.ts} +2 -3
  472. package/src/utils/index.ts +14 -0
  473. package/src/{license.ts → utils/license.ts} +1 -1
  474. package/src/{parquet.ts → utils/parquet.ts} +22 -9
  475. package/src/{split.ts → utils/split.ts} +3 -3
  476. package/out/src/adapter.d.ts.map +0 -1
  477. package/out/src/adapter.js.map +0 -1
  478. package/out/src/align.d.ts.map +0 -1
  479. package/out/src/align.js.map +0 -1
  480. package/out/src/format.d.ts +0 -14
  481. package/out/src/format.d.ts.map +0 -1
  482. package/out/src/format.js +0 -14
  483. package/out/src/format.js.map +0 -1
  484. package/out/src/golden.d.ts.map +0 -1
  485. package/out/src/golden.js.map +0 -1
  486. package/out/src/license.d.ts.map +0 -1
  487. package/out/src/license.js.map +0 -1
  488. package/out/src/parquet.d.ts.map +0 -1
  489. package/out/src/parquet.js.map +0 -1
  490. package/out/src/split.d.ts.map +0 -1
  491. package/out/src/split.js.map +0 -1
  492. package/out/src/synthesize-anchor-absorption.d.ts.map +0 -1
  493. package/out/src/synthesize-anchor-absorption.js.map +0 -1
  494. package/out/src/synthesize-boundary-stress.d.ts.map +0 -1
  495. package/out/src/synthesize-boundary-stress.js.map +0 -1
  496. package/out/src/synthesize-german.d.ts.map +0 -1
  497. package/out/src/synthesize-german.js.map +0 -1
  498. package/out/src/synthesize-house-venue.d.ts.map +0 -1
  499. package/out/src/synthesize-house-venue.js.map +0 -1
  500. package/out/src/synthesize-intersection.d.ts.map +0 -1
  501. package/out/src/synthesize-intersection.js.map +0 -1
  502. package/out/src/synthesize-no-street.d.ts.map +0 -1
  503. package/out/src/synthesize-no-street.js.map +0 -1
  504. package/out/src/synthesize-po-box.d.ts.map +0 -1
  505. package/out/src/synthesize-po-box.js.map +0 -1
  506. package/out/src/synthesize-street.d.ts.map +0 -1
  507. package/out/src/synthesize-street.js.map +0 -1
  508. package/out/src/synthesize.d.ts.map +0 -1
  509. package/out/src/synthesize.js.map +0 -1
  510. package/out/src/tokenize.d.ts.map +0 -1
  511. package/out/src/tokenize.js.map +0 -1
  512. package/out/src/wof-json.d.ts.map +0 -1
  513. package/out/src/wof-json.js.map +0 -1
  514. package/src/format.ts +0 -14
  515. /package/out/src/{align.js → utils/align.js} +0 -0
  516. /package/out/src/{golden.d.ts → utils/golden.d.ts} +0 -0
  517. /package/out/src/{license.d.ts → utils/license.d.ts} +0 -0
  518. /package/out/src/{tokenize.d.ts → utils/tokenize.d.ts} +0 -0
  519. /package/out/src/{tokenize.js → utils/tokenize.js} +0 -0
  520. /package/out/src/{wof-json.d.ts → utils/wof-json.d.ts} +0 -0
  521. /package/out/src/{wof-json.js → utils/wof-json.js} +0 -0
  522. /package/src/{synthesize-anchor-absorption.ts → synthesizers/anchor-absorption.ts} +0 -0
  523. /package/src/{tokenize.ts → utils/tokenize.ts} +0 -0
  524. /package/src/{wof-json.ts → utils/wof-json.ts} +0 -0
@@ -0,0 +1,183 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * `trailing-region` — the `«locality», «region», «country»` admin tail, the Portopetro class
7
+ * (board row `es-op3-southeast-portopetro`): `…, 07691 Portopetro, Illes Balears, Spain` parsed
8
+ * with the REGION mislabeled `locality` and the true locality dropped entirely. Spanish sources
9
+ * are postcode-complete and rarely write the region, so the trailing-region segment is
10
+ * under-attested and the model reads the last populous name as the locality.
11
+ *
12
+ * Tuples are real `(locality, region)` ancestor pairs from the WOF admin DB (the fr-hood-pairs
13
+ * extraction shape). Two surface forms per pair — with and without the trailing country — so the
14
+ * region is attested both as the middle and the final segment. A bare `«region»` form is
15
+ * deliberately absent: that surface is the bare-toponym class with its own rules, and teaching it
16
+ * here as `region` would fight the locality/region ambiguity the dominance race arbitrates.
17
+ *
18
+ * The recipe is country-agnostic; the country tail surface comes from the tuple's `country`
19
+ * field ("Spain", "United Kingdom") so one recipe serves every extraction.
20
+ *
21
+ * POSTCODE-PREFIXED FORMS (2026-08-20, #1748). The two bare forms above were the whole shard, and the
22
+ * board row this recipe was written for is NOT bare — it reads `…, 07691 Portopetro, Illes Balears,
23
+ * Spain`. Measured over both built shards: 88,904 rows, zero containing a postcode. So the model
24
+ * learned the bare tail correctly and had never once seen the shape it was failing on, which is why no
25
+ * decode lever moved it.
26
+ *
27
+ * The collapse is two-staged and neither trigger is a street, which is what makes this cheap to teach:
28
+ *
29
+ * Portopetro, Illes Balears, Spain locality ✓ region ✓
30
+ * 07691 Portopetro, Illes Balears, Spain locality ✓ region DISCARDED
31
+ * 15, 07691 Portopetro, Illes Balears, Spain locality DISPLACED by the region
32
+ *
33
+ * A postcode alone drops the region (every locale measured); a house number then displaces the
34
+ * locality. So the added surfaces are postcode-prefixed and house-number-plus-postcode-prefixed, and
35
+ * the shard still needs no street names.
36
+ *
37
+ * POSTCODE PLACEMENT. The three surfaces above are the LEADING form, and for a long time they were the
38
+ * only one, so this shard taught only the countries that write the postcode first. That is a real gap
39
+ * and not a stylistic one, because the same digits change TAG with position. Measured on the shipped
40
+ * model: `Barcelona 6001, Anzoátegui, Venezuela` tags `6001` as `house_number` and loses the locality
41
+ * into the street, while `6001 Barcelona, Anzoátegui, Venezuela` tags it `postcode` and recovers
42
+ * `locality: Barcelona`. `Sandton 2196` vs `2196 Sandton` behaves the same way, and no decode-time
43
+ * lever moves it — `postcodeShapeCoherence: true` leaves all eight VE board rows byte-identical.
44
+ *
45
+ * So the tuple's `postcodePlacement` selects the surface, and it keeps apart two trailing conventions
46
+ * that are NOT the same shape: VE writes `Barcelona 6001, Anzoátegui, Venezuela` (the code on the
47
+ * LOCALITY segment) and IN writes `…, Bengaluru, Karnataka 560038, India` (on the REGION segment).
48
+ * Each of the three placements matches a board row verbatim. A tuple with no placement means `leading`,
49
+ * so a tuples file written before the field existed produces the rows it always did.
50
+ *
51
+ * LEFT CONTEXT (v25). A tuple may carry a `dependentLocality`, and when it does the surface becomes
52
+ * `«dep_locality», «locality»…`. This is not decoration: without it EVERY row in the shard begins with
53
+ * the locality, and at a 9.4% share that taught the model the first named segment is the locality.
54
+ * Measured on the v4.8.0 candidate — `Ye Three Lords, 27 Minories, London EC3N 1DE` came back
55
+ * `locality: "Ye Three Lords"` with venue and street both gone, `Le Colimaçon, 44 Rue Vieille du
56
+ * Temple, 75004 Paris` came back `locality: "Le Colimaçon"`, and 11 of 25 regressions were venue-led
57
+ * rows across seven countries. The house-number prefix does NOT supply this: a number before the
58
+ * locality does not teach that a NAME can precede one. `no-fragment.ts`'s header records the same
59
+ * trap from the other direction.
60
+ *
61
+ * The (postcode, locality, region) triples are REAL — `postalcode-intl.db` parents joined to admin
62
+ * localities and their region ancestors — with one filter that had to be measured rather than assumed.
63
+ * A handful of localities act as catch-all parents: `Schwedt/Oder` claims 9,222 postcodes, `Korb`
64
+ * 4,846, against a p50 of 1 and a p99 of 53. Eight such hubs held 47% of the join. Capping at the p99
65
+ * drops them and keeps 17,908 triples. The house number is synthetic because a house number asserts no
66
+ * fact about a place; the postcode is not, because it does.
67
+ */
68
+
69
+ import {
70
+ alignAndWrite,
71
+ makeMulberry32,
72
+ type PostcodePlacement,
73
+ readTuples,
74
+ type ShardRecipe,
75
+ shardSourceID,
76
+ } from "./scaffold.ts"
77
+
78
+ /**
79
+ * Shard recipe registered with the corpus builder — see the file header for the parse behaviour it exists to exercise,
80
+ * and `description` below for the surface form it generates.
81
+ */
82
+ export const trailingRegionRecipe: ShardRecipe = {
83
+ name: "trailing-region",
84
+ description: "Admin tails (Portopetro class): '«locality», «region»[, «country»]' from WOF ancestor pairs",
85
+ mode: "tuples",
86
+ async run(opts, write) {
87
+ makeMulberry32(opts.seed)
88
+ let read = 0
89
+ let emitted = 0
90
+ let skipped = 0
91
+
92
+ for await (const t of readTuples(opts.input!)) {
93
+ read++
94
+ const locality = String(t.locality ?? "").trim()
95
+ const region = String(t.region ?? "").trim()
96
+ const country = String(t.country ?? "").trim()
97
+ const dependentLocality = String(t.dependentLocality ?? "").trim()
98
+
99
+ // A pair whose region EQUALS its locality (Santa Cruz de Tenerife inside Santa Cruz de
100
+ // Tenerife) teaches nothing about the boundary this shard exists for.
101
+ if (!locality || !region || locality === region) {
102
+ skipped++
103
+
104
+ continue
105
+ }
106
+
107
+ const withCountry = read % 2 === 0 && country.length > 0
108
+ const postcode = String(t.postcode ?? "").trim()
109
+
110
+ // A tuple carrying a postcode emits the STRUCTURED tail — the shape the bare-only shard never
111
+ // contained. Every fourth such row also carries a house number, which is the second trigger:
112
+ // the postcode discards the region, the house number then displaces the locality.
113
+ const withHouseNumber = postcode.length > 0 && read % 4 === 1
114
+ const houseNumber = withHouseNumber ? String((read % 97) + 1) : ""
115
+
116
+ const components: Record<string, string> = { locality, region }
117
+
118
+ // LEFT CONTEXT. Without it every row begins with the locality, and the shard teaches that the first named
119
+ // segment IS the locality — measured on the v4.8.0 candidate: `Ye Three Lords, 27 Minories, London EC3N 1DE`
120
+ // came back `locality: "Ye Three Lords"` with the venue and street gone, and 11 of its 25 regressions were
121
+ // venue-led rows across seven countries. The house-number prefix does not supply it, because a NUMBER before
122
+ // the locality does not teach that a NAME can precede one.
123
+ if (dependentLocality && dependentLocality !== locality) {
124
+ components["dependent_locality"] = dependentLocality
125
+ }
126
+
127
+ if (withCountry) {
128
+ components["country"] = country
129
+ }
130
+
131
+ if (postcode) {
132
+ components["postcode"] = postcode
133
+ }
134
+
135
+ if (withHouseNumber) {
136
+ components["house_number"] = houseNumber
137
+ }
138
+
139
+ const placement = (t.postcodePlacement as PostcodePlacement | undefined) ?? "leading"
140
+ // Both trailing placements put the code inside the ADMIN tail; they differ in which segment carries it.
141
+ const bareLocality = postcode && placement === "after_locality" ? `${locality} ${postcode}` : locality
142
+
143
+ const localitySegment =
144
+ components["dependent_locality"] === undefined ? bareLocality : `${dependentLocality}, ${bareLocality}`
145
+
146
+ const regionSegment = postcode && placement === "after_region" ? `${region} ${postcode}` : region
147
+
148
+ const tail = withCountry
149
+ ? `${localitySegment}, ${regionSegment}, ${country}`
150
+ : `${localitySegment}, ${regionSegment}`
151
+
152
+ // A leading postcode joins the head, ahead of the locality; the other two are already in the tail, so the
153
+ // head carries at most the house number.
154
+ const leadingPostcode = postcode && placement === "leading" ? `${postcode} ` : ""
155
+ const head = withHouseNumber ? `${houseNumber}, ${leadingPostcode}` : leadingPostcode
156
+ const raw = `${head}${tail}`
157
+ // A DISTINCT source for the structured rows. The sampler buckets by `source` and weights each bucket,
158
+ // so emitting these under `synth-trailing-region` would pool them with the 88,904 bare rows and make
159
+ // the new surface unweightable — the dose would silently be whatever the bare shard's weight bought.
160
+ const sourceLabel = postcode ? "synth-trailing-region-structured" : "synth-trailing-region"
161
+ const source_id = shardSourceID(sourceLabel, { ...components, v: String(read) })
162
+
163
+ const canonical = {
164
+ raw,
165
+ components,
166
+ country: String(t.cc ?? "").trim() || "und",
167
+ locale: String(t.locale ?? "und"),
168
+ source: sourceLabel,
169
+ source_id,
170
+ corpus_version: "0.11.0",
171
+ license: "Synthetic — trailing-region; (locality, region) ancestor pairs from WOF (CC0/ODC-By per source)",
172
+ }
173
+
174
+ if (alignAndWrite(write, canonical, "trailing-region")) {
175
+ emitted++
176
+ } else {
177
+ skipped++
178
+ }
179
+ }
180
+
181
+ return { read, emitted, skipped }
182
+ },
183
+ }
@@ -21,16 +21,15 @@
21
21
  * framework LCG) is consumed in the exact call order the legacy script used.
22
22
  */
23
23
 
24
- import { spawnSync } from "node:child_process"
25
-
26
24
  import { US_UNIT_DESIGNATOR_PREFERRED_ABBR, type USUnitDesignator } from "@mailwoman/codex/us"
27
25
  import type { ComponentTag } from "@mailwoman/core/types"
28
26
  import { dataRootPath } from "@mailwoman/core/utils"
29
27
 
30
- import { stableSourceID } from "../adapter.ts"
31
- import { alignRow } from "../align.ts"
32
- import type { CanonicalRow } from "../types.ts"
33
- import { makeMulberry32, readCSVRecords, type ShardRecipe } from "./scaffold.ts"
28
+ import { stableSourceID } from "#adapters/utils"
29
+ import type { CanonicalRow } from "#types"
30
+ import { alignRow } from "#utils"
31
+
32
+ import { makeMulberry32, readZippedCSVRecords, type ShardRecipe } from "./scaffold.ts"
34
33
 
35
34
  /**
36
35
  * A cached OpenAddresses extract: the zip, the CSV member, and the implied (file-level) region.
@@ -122,19 +121,11 @@ interface UnitTuple {
122
121
  /**
123
122
  * Stream real US tuples (number/street/city/postcode + the bare OA unit id) out of a cached OA zip.
124
123
  */
125
- function readTuples(source: UnitSource): UnitTuple[] {
126
- const r = spawnSync("unzip", ["-p", source.zip, source.csv], { maxBuffer: 1024 * 1024 * 1024, encoding: "buffer" })
127
-
128
- if (r.status !== 0) {
129
- console.error(` WARN: unzip failed for ${source.zip} (status ${r.status})`)
130
-
131
- return []
132
- }
133
-
124
+ async function readTuples(source: UnitSource): Promise<UnitTuple[]> {
134
125
  const tuples: UnitTuple[] = []
135
126
  const seen = new Set<string>()
136
127
 
137
- for (const row of readCSVRecords(r.stdout)) {
128
+ for await (const row of readZippedCSVRecords(source.zip, source.csv)) {
138
129
  const street = row.street ?? ""
139
130
  const locality = row.city ?? ""
140
131
  const house_number = row.number ?? ""
@@ -263,7 +254,7 @@ export const unitRecipe: ShardRecipe = {
263
254
  const pool: UnitTuple[] = []
264
255
 
265
256
  for (const s of sources) {
266
- const t = readTuples(s)
257
+ const t = await readTuples(s)
267
258
 
268
259
  console.error(` ${s.csv}: ${t.length} unique tuples`)
269
260
 
@@ -46,10 +46,10 @@
46
46
  * tokenizer splits `/`) and is the worst within-token class — but it inherently requires non-base
47
47
  * AU/NZ/UK locales, which contradict the US/FR/DE base (the lint catch). It belongs in a
48
48
  * separately-scoped AU/NZ/UK boundary-coverage shard that ALSO adds AU base coverage, not in this
49
- * base-locale shard. `synthesize-boundary-stress.test.ts` proves the alignments.
49
+ * base-locale shard. `synthesizers/boundary-stress.test.ts` proves the alignments.
50
50
  */
51
51
 
52
- import type { CanonicalRow } from "./types.ts"
52
+ import type { CanonicalRow } from "#types"
53
53
 
54
54
  /* oxlint-disable sister-software/no-unnamed-threshold -- the bare decimals below are weighted-sampler
55
55
  cutoffs, not thresholds: `const r = random()` followed by a cascade of `r < 0.4` branches IS the
@@ -22,8 +22,9 @@
22
22
  * `raw` so alignment lands.
23
23
  */
24
24
 
25
- import { formatAddress } from "./format.ts"
26
- import type { CanonicalRow } from "./types.ts"
25
+ import { formatAddress } from "@mailwoman/formatter"
26
+
27
+ import type { CanonicalRow } from "#types"
27
28
 
28
29
  /**
29
30
  * A real address tuple (e.g. one OpenAddresses row): street + locality required, rest optional.
@@ -9,7 +9,7 @@
9
9
  * house_number recall by ~4-5pp. DeepSeek's turn-8 root-cause:
10
10
  *
11
11
  * 1. Direct: `5th Avenue Theatre`-style adversarial venues teach the model that tokens like "5th"
12
- * belong to venues, not house_numbers. (Fixed in `synthesize-no-street.ts` by removing
12
+ * belong to venues, not house_numbers. (Fixed in `no-street.ts` by removing
13
13
  * digit+ordinal venue patterns.)
14
14
  * 2. Distributional dilution: synth-no-street adds 122K rows where house_number is absent. The model's
15
15
  * training distribution shifts toward "house_number is rare," and it under-emits the tag at
@@ -23,12 +23,12 @@
23
23
  * Real-world shape: business cards, mailing labels, store directories — `"123 Main St, Sunrise
24
24
  * Bakery, Springfield, IL 62701"` is a perfectly ordinary address form.
25
25
  *
26
- * Venue pool: PLAIN_VENUES from `synthesize-no-street.ts` (re-exported here). Adversarial venues
26
+ * Venue pool: PLAIN_VENUES from `no-street.ts` (re-exported here). Adversarial venues
27
27
  * are deliberately NOT used here — the point is to teach co-occurrence, not to re-introduce
28
28
  * decompose-mode pressure.
29
29
  */
30
30
 
31
- import type { CanonicalRow } from "./types.ts"
31
+ import type { CanonicalRow } from "#types"
32
32
 
33
33
  export interface HouseVenueBaseTuple {
34
34
  locality: string
@@ -61,7 +61,7 @@ export interface SynthesizedHouseVenueRow {
61
61
 
62
62
  /**
63
63
  * PLAIN venue names, carrying no street-typing tokens. This shard teaches house_number + venue coexistence, NOT
64
- * decompose-mode pressure — adversarial venue names live in `synthesize-no-street.ts`.
64
+ * decompose-mode pressure — adversarial venue names live in `no-street.ts`.
65
65
  */
66
66
  const PLAIN_VENUES: ReadonlyArray<string> = [
67
67
  "Bob's Pizza",
@@ -245,9 +245,21 @@ export function synthesizeHouseVenueRow(
245
245
  // 75005 Paris" — the v4.0.0 gauntlet's venue-led failure family, the run-2 contingency's exact
246
246
  // target shape). GB (#1366) renders locality-then-postcode with NO region and NO comma between
247
247
  // them ("Ye Three Lords, 27 Minories, London EC3N 1DE" — the third tail the shard must teach).
248
- // Every other country keeps the original US-order tail.
248
+ // VE (#1821) renders locality-then-postcode and KEEPS the region after it. Every other country
249
+ // keeps the original US-order tail, which is itself the `after_region` surface — `Springfield, IL
250
+ // 02101` and `Bengaluru, Karnataka 560038` are the same shape.
249
251
  const frOrder = base.country === "FR"
250
252
  const gbOrder = base.country === "GB"
253
+ // VE writes the code on the LOCALITY segment with the region still after it — `…, Barcelona 6001, Anzoátegui,
254
+ // Venezuela`, the four `ve_city_postcode_trailing_state` board rows. That is neither GB's form (which drops the
255
+ // region) nor the default (which puts the region before the code), so it needs its own branch.
256
+ //
257
+ // It belongs HERE rather than in a standalone admin shard, and that is measured: three trailing-region shards
258
+ // carrying only admin segments all graded DO-NOT-SHIP, and the way they failed was by damaging the classes they did
259
+ // not contain — v4.8.0 turned `Ye Three Lords, 27 Minories, London EC3N 1DE` into `locality: "Ye Three Lords"`,
260
+ // losing the venue and the street. Every row this synthesizer emits carries a venue, a street AND a house number,
261
+ // so the surface is taught with the alternatives present rather than against them.
262
+ const veOrder = base.country === "VE"
251
263
 
252
264
  // GB rows draw from the GB pool 70% of the time (institutional/archaic/brand-dash-place forms,
253
265
  // incl. directional-led names — the #1366 target class) and the shared pool otherwise; real GB
@@ -280,7 +292,9 @@ export function synthesizeHouseVenueRow(
280
292
  ? `${base.postcode} ${base.locality}`
281
293
  : gbOrder
282
294
  ? `${base.locality} ${base.postcode}`
283
- : `${base.locality}, ${base.region} ${base.postcode}`
295
+ : veOrder
296
+ ? `${base.locality} ${base.postcode}, ${base.region}`
297
+ : `${base.locality}, ${base.region} ${base.postcode}`
284
298
 
285
299
  // Trailing country surface (Addendum 3): appended AFTER the tail in every order, tagged.
286
300
  const countrySurfaces = COUNTRY_SURFACES[base.country]
@@ -19,7 +19,7 @@
19
19
  * US-idiomatic only (the harness intersection cases are US: "X & Y, City, ST ZIP").
20
20
  */
21
21
 
22
- import type { CanonicalRow } from "./types.ts"
22
+ import type { CanonicalRow } from "#types"
23
23
 
24
24
  /**
25
25
  * Street name cores (no suffix) — proper-noun streets that often appear bare.
@@ -34,10 +34,10 @@
34
34
  * counter-example signal the model is missing.
35
35
  *
36
36
  * This complements (does not replace) the existing US-base-tuple source used by
37
- * `synthesize-po-box.ts`; the same `NoStreetBaseTuple` shape is consumed.
37
+ * `po-box.ts`; the same `NoStreetBaseTuple` shape is consumed.
38
38
  */
39
39
 
40
- import type { CanonicalRow } from "./types.ts"
40
+ import type { CanonicalRow } from "#types"
41
41
 
42
42
  //#region Types
43
43
 
@@ -24,7 +24,7 @@
24
24
  * - USPS DMM 508 §4.1.4 / §4.5.4 — PO Box and street-addressed PO Box
25
25
  */
26
26
 
27
- import type { CanonicalRow } from "./types.ts"
27
+ import type { CanonicalRow } from "#types"
28
28
 
29
29
  /**
30
30
  * Digits a box number needs before a thousands comma is plausible (`1,234`).
@@ -19,8 +19,10 @@
19
19
  * adapter.
20
20
  */
21
21
 
22
- import { decomposeStreet } from "./adapters/tiger/street-decompose.ts"
23
- import type { CanonicalRow } from "./types.ts"
22
+ import { isPresent } from "@mailwoman/core/objects"
23
+
24
+ import { decomposeStreet } from "#adapters/tiger/street-decompose"
25
+ import type { CanonicalRow } from "#types"
24
26
 
25
27
  // Hand-curated US street name pool. Real frequency-weighted street names — sampled
26
28
  // from US Census TIGER 2024 top-1000 by occurrence count. Keep ~50 entries so the
@@ -223,7 +225,7 @@ export function synthesizeStreetRow(
223
225
  const trailing = pick(TRAILING_DIRECTIONALS, random)
224
226
 
225
227
  // Build the "full" street string the adapter would receive from TIGER FULLNAME.
226
- const parts = [prefix, name, suffix, trailing].filter(Boolean)
228
+ const parts = [prefix, name, suffix, trailing].filter(isPresent)
227
229
  const fullStreet = parts.join(" ")
228
230
 
229
231
  // Pass through the same decomposeStreet TIGER uses — match the training distribution.
@@ -33,12 +33,14 @@ import {
33
33
  matchLeadingDesignator,
34
34
  matchTrailingSuffix,
35
35
  } from "@mailwoman/codex/us"
36
+ import { isPresent } from "@mailwoman/core/objects"
36
37
  import type { BIOLabel, ComponentTag } from "@mailwoman/core/types"
37
38
  import { mulberry32 } from "@mailwoman/core/utils"
38
39
 
39
- import { alignRow, assertSpanInvariants, type ComponentSpan } from "./align.ts"
40
- import { whitespaceTokenizer, type Tokenizer } from "./tokenize.ts"
41
- import type { CanonicalRow, LabeledRow, QuarantinedRow } from "./types.ts"
40
+ import type { CanonicalRow, LabeledRow, QuarantinedRow } from "#types"
41
+ import { alignRow, assertSpanInvariants, type ComponentSpan } from "#utils/align"
42
+
43
+ import { whitespaceTokenizer, type Tokenizer } from "../utils/tokenize.ts"
42
44
 
43
45
  /**
44
46
  * An augmentation transforms a single row. Return `null` if the augmentation doesn't apply (e.g. accent-strip on a row
@@ -238,7 +240,7 @@ export const typoInject: Augmentation = (row) => {
238
240
  return n
239
241
  }
240
242
 
241
- const values = Object.values(row.components).filter(Boolean) as string[]
243
+ const values = Object.values(row.components).filter(isPresent)
242
244
 
243
245
  const eligible = (Object.entries(row.components) as Array<[ComponentTag, string]>).filter(
244
246
  ([, v]) => v && ALPHA_NAME.test(v) && occurs(v) === 1 && !values.some((o) => o !== v && o.includes(v))
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createWriteStream } from "node:fs"
3
3
 
4
+ import { JSONSpliterator } from "spliterator"
5
+
4
6
  /**
5
7
  * Re-emit a CANONICAL jsonl ({raw, components, country, source, ...}) as a LABELED jsonl in the CURRENT align format,
6
8
  * by running every row through `alignRow` (corpus/src/align.ts).
@@ -26,8 +28,7 @@ import { createWriteStream } from "node:fs"
26
28
  * --output /tmp/kryptonite-labeled.jsonl\
27
29
  * --corpus-version 0.5.0
28
30
  */
29
- import { alignRow } from "@mailwoman/corpus"
30
- import { JSONSpliterator } from "spliterator"
31
+ import { alignRow } from "#utils"
31
32
 
32
33
  export interface AlignShardOptions {
33
34
  input: string
@@ -24,6 +24,7 @@ import { join } from "node:path"
24
24
  import { setTimeout as sleep } from "node:timers/promises"
25
25
  import { gunzipSync } from "node:zlib"
26
26
 
27
+ import { BYTES_PER_KIB, ByteFormatter } from "@mailwoman/core/fs/utils"
27
28
  import { sha256File } from "@mailwoman/core/utils"
28
29
 
29
30
  import type { BaseFetchOptions, FetchSummary } from "./download.ts"
@@ -33,7 +34,6 @@ import { downloadToFile, loadManifestEntries, writeManifest } from "./download.t
33
34
  * Bytes per KiB — the divisor for human-readable sizes, and the floor below which a "download" is an error page rather
34
35
  * than data.
35
36
  */
36
- const BYTES_PER_KIB = 1024
37
37
 
38
38
  const BASE_URL = "https://adresse.data.gouv.fr/data/ban/adresses/latest/csv"
39
39
 
@@ -156,26 +156,6 @@ export interface BanManifestEntry {
156
156
 
157
157
  export type FetchBanOptions = BaseFetchOptions
158
158
 
159
- /**
160
- * Mimic `numfmt --to=iec` for a friendly byte-size log line.
161
- */
162
- function iec(bytes: number): string {
163
- if (bytes < BYTES_PER_KIB) return String(bytes)
164
- const units = ["K", "M", "G", "T", "P"]
165
- let value = bytes / 1024
166
- let i = 0
167
-
168
- while (value >= BYTES_PER_KIB && i < units.length - 1) {
169
- value /= 1024
170
-
171
- i++
172
- }
173
-
174
- const rounded = value < 10 ? value.toFixed(1) : Math.round(value).toString()
175
-
176
- return `${rounded}${units[i] ?? ""}`
177
- }
178
-
179
159
  export async function fetchBan(options: FetchBanOptions, report?: (line: string) => void): Promise<FetchSummary> {
180
160
  const banDir = join(options.outRoot, "ban")
181
161
  const manifestPath = join(banDir, "MANIFEST.json")
@@ -281,7 +261,7 @@ export async function fetchBan(options: FetchBanOptions, report?: (line: string)
281
261
  bytes,
282
262
  })
283
263
 
284
- report?.(` ✓ ${iec(bytes)} sha256=${sha}`)
264
+ report?.(` ✓ ${ByteFormatter.formatIEC(bytes)} sha256=${sha}`)
285
265
 
286
266
  fetched++
287
267
 
@@ -3,9 +3,7 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * Download + manifest plumbing for the `mailwoman corpus fetch <source>` family — one download-with-retry and
7
- * one MANIFEST.json idiom instead of the per-script clones the 2026-07-09 dedupe survey counted
8
- * (6× `downloadToFile`, 2× `isTransientStatus`, 9× manifest writes).
6
+ * Download and manifest utilities for `mailwoman corpus fetch <source>`.
9
7
  */
10
8
 
11
9
  import { existsSync } from "node:fs"
@@ -52,6 +50,23 @@ export interface FetchSummary {
52
50
  /**
53
51
  * A status worth retrying: rate limiting or a server-side failure.
54
52
  */
53
+ /**
54
+ * An HTTP failure that CARRIES its status, so callers branch on `error.status` rather than on message prose. The prose
55
+ * route shipped a real flake: a caller classified "not published upstream" with `message.includes("404")`, and the
56
+ * message contains the URL — an ephemeral test-server port such as `:40453` satisfies it while the actual status is
57
+ * 500. Roughly 1–2% of ephemeral ports contain the substring, which is exactly the kind of sometimes-failure that burns
58
+ * a CI run and vanishes locally.
59
+ */
60
+ export class HTTPStatusError extends Error {
61
+ readonly status: number
62
+
63
+ constructor(status: number, message: string) {
64
+ super(message)
65
+ this.name = "HTTPStatusError"
66
+ this.status = status
67
+ }
68
+ }
69
+
55
70
  export function isTransientStatus(status: number): boolean {
56
71
  return status === HTTP_TOO_MANY_REQUESTS || (status >= HTTP_SERVER_ERROR_MIN && status <= HTTP_SERVER_ERROR_MAX)
57
72
  }
@@ -92,6 +107,9 @@ export async function downloadToFile(options: DownloadOptions): Promise<{ bytes:
92
107
  let res: Response
93
108
 
94
109
  try {
110
+ // Raw `fetch`, deliberately: this is the shared FILE downloader and the body is piped to disk below.
111
+ // `APIClient` is the repo default for API requests — small bodies, repeated calls — and buffers a
112
+ // non-stream response in memory, which is the one thing a multi-gigabyte transfer must not do.
95
113
  res = await fetch(url, { headers, signal: AbortSignal.timeout(timeoutMs) })
96
114
  } catch (error) {
97
115
  // AbortSignal timeouts and network-level failures are retryable.
@@ -101,7 +119,7 @@ export async function downloadToFile(options: DownloadOptions): Promise<{ bytes:
101
119
  }
102
120
 
103
121
  if (!res.ok) {
104
- const error = new Error(`HTTP ${res.status} ${res.statusText} — ${url}`)
122
+ const error = new HTTPStatusError(res.status, `HTTP ${res.status} ${res.statusText} — ${url}`)
105
123
 
106
124
  if (!isTransientStatus(res.status)) throw error
107
125
  lastError = error