@mailwoman/corpus 9.1.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 (436) hide show
  1. package/README.md +2 -2
  2. package/data/PROVENANCE.md +13 -0
  3. package/data/reviewed-ve-postcode-tuples.json +74 -0
  4. package/out/src/adapters/ban/adapter.d.ts +1 -1
  5. package/out/src/adapters/ban/adapter.d.ts.map +1 -1
  6. package/out/src/adapters/ban/adapter.js +4 -3
  7. package/out/src/adapters/ban/adapter.js.map +1 -1
  8. package/out/src/adapters/fcc-bdc/adapter.d.ts +1 -1
  9. package/out/src/adapters/fcc-bdc/adapter.d.ts.map +1 -1
  10. package/out/src/adapters/fcc-bdc/adapter.js +2 -2
  11. package/out/src/adapters/fcc-bdc/adapter.js.map +1 -1
  12. package/out/src/adapters/geonames/adapter.d.ts +1 -1
  13. package/out/src/adapters/geonames/adapter.d.ts.map +1 -1
  14. package/out/src/adapters/geonames/adapter.js +1 -1
  15. package/out/src/adapters/geonames/adapter.js.map +1 -1
  16. package/out/src/adapters/geonames-postal/adapter.d.ts +1 -1
  17. package/out/src/adapters/geonames-postal/adapter.d.ts.map +1 -1
  18. package/out/src/adapters/geonames-postal/adapter.js +2 -2
  19. package/out/src/adapters/geonames-postal/adapter.js.map +1 -1
  20. package/out/src/adapters/gnaf/adapter.d.ts +1 -1
  21. package/out/src/adapters/gnaf/adapter.d.ts.map +1 -1
  22. package/out/src/adapters/gnaf/adapter.js +1 -1
  23. package/out/src/adapters/gnaf/adapter.js.map +1 -1
  24. package/out/src/adapters/index.d.ts +1 -1
  25. package/out/src/adapters/index.d.ts.map +1 -1
  26. package/out/src/adapters/index.js +1 -1
  27. package/out/src/adapters/index.js.map +1 -1
  28. package/out/src/adapters/openaddresses/adapter.d.ts +1 -1
  29. package/out/src/adapters/openaddresses/adapter.d.ts.map +1 -1
  30. package/out/src/adapters/openaddresses/adapter.js +2 -2
  31. package/out/src/adapters/openaddresses/adapter.js.map +1 -1
  32. package/out/src/adapters/overture/adapter.d.ts +1 -1
  33. package/out/src/adapters/overture/adapter.d.ts.map +1 -1
  34. package/out/src/adapters/overture/adapter.js +1 -1
  35. package/out/src/adapters/overture/adapter.js.map +1 -1
  36. package/out/src/adapters/state-hi-schools/adapter.d.ts +1 -1
  37. package/out/src/adapters/state-hi-schools/adapter.d.ts.map +1 -1
  38. package/out/src/adapters/state-hi-schools/adapter.js +6 -5
  39. package/out/src/adapters/state-hi-schools/adapter.js.map +1 -1
  40. package/out/src/adapters/state-ia-contractors/adapter.d.ts +1 -1
  41. package/out/src/adapters/state-ia-contractors/adapter.d.ts.map +1 -1
  42. package/out/src/adapters/state-ia-contractors/adapter.js +11 -6
  43. package/out/src/adapters/state-ia-contractors/adapter.js.map +1 -1
  44. package/out/src/adapters/state-ny-notaries/adapter.d.ts +1 -1
  45. package/out/src/adapters/state-ny-notaries/adapter.d.ts.map +1 -1
  46. package/out/src/adapters/state-ny-notaries/adapter.js +11 -17
  47. package/out/src/adapters/state-ny-notaries/adapter.js.map +1 -1
  48. package/out/src/adapters/state-tx-notaries/adapter.d.ts +1 -1
  49. package/out/src/adapters/state-tx-notaries/adapter.d.ts.map +1 -1
  50. package/out/src/adapters/state-tx-notaries/adapter.js +11 -6
  51. package/out/src/adapters/state-tx-notaries/adapter.js.map +1 -1
  52. package/out/src/adapters/synth-po-box/adapter.d.ts +2 -2
  53. package/out/src/adapters/synth-po-box/adapter.d.ts.map +1 -1
  54. package/out/src/adapters/synth-po-box/adapter.js +2 -2
  55. package/out/src/adapters/synth-po-box/adapter.js.map +1 -1
  56. package/out/src/adapters/tiger/adapter.d.ts +1 -1
  57. package/out/src/adapters/tiger/adapter.d.ts.map +1 -1
  58. package/out/src/adapters/tiger/adapter.js +1 -1
  59. package/out/src/adapters/tiger/adapter.js.map +1 -1
  60. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +1 -1
  61. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts.map +1 -1
  62. package/out/src/adapters/usgov-hrsa-fqhc/adapter.js +6 -5
  63. package/out/src/adapters/usgov-hrsa-fqhc/adapter.js.map +1 -1
  64. package/out/src/adapters/usgov-imls-pls/adapter.d.ts +1 -1
  65. package/out/src/adapters/usgov-imls-pls/adapter.d.ts.map +1 -1
  66. package/out/src/adapters/usgov-imls-pls/adapter.js +10 -6
  67. package/out/src/adapters/usgov-imls-pls/adapter.js.map +1 -1
  68. package/out/src/adapters/usgov-irs-bmf/adapter.d.ts +1 -1
  69. package/out/src/adapters/usgov-irs-bmf/adapter.d.ts.map +1 -1
  70. package/out/src/adapters/usgov-irs-bmf/adapter.js +5 -4
  71. package/out/src/adapters/usgov-irs-bmf/adapter.js.map +1 -1
  72. package/out/src/adapters/usgov-nad/adapter.d.ts +1 -1
  73. package/out/src/adapters/usgov-nad/adapter.d.ts.map +1 -1
  74. package/out/src/adapters/usgov-nad/adapter.js +7 -7
  75. package/out/src/adapters/usgov-nad/adapter.js.map +1 -1
  76. package/out/src/adapters/usgov-nppes/adapter.d.ts +1 -1
  77. package/out/src/adapters/usgov-nppes/adapter.d.ts.map +1 -1
  78. package/out/src/adapters/usgov-nppes/adapter.js +9 -9
  79. package/out/src/adapters/usgov-nppes/adapter.js.map +1 -1
  80. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts +1 -1
  81. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts.map +1 -1
  82. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js +6 -5
  83. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js.map +1 -1
  84. package/out/src/adapters/utils/index.d.ts +7 -1
  85. package/out/src/adapters/utils/index.d.ts.map +1 -1
  86. package/out/src/adapters/utils/index.js +10 -2
  87. package/out/src/adapters/utils/index.js.map +1 -1
  88. package/out/src/adapters/wof-admin-jp/adapter.d.ts +1 -1
  89. package/out/src/adapters/wof-admin-jp/adapter.d.ts.map +1 -1
  90. package/out/src/adapters/wof-admin-jp/adapter.js +5 -5
  91. package/out/src/adapters/wof-admin-jp/adapter.js.map +1 -1
  92. package/out/src/adapters/wof-admin-json/adapter.d.ts +4 -15
  93. package/out/src/adapters/wof-admin-json/adapter.d.ts.map +1 -1
  94. package/out/src/adapters/wof-admin-json/adapter.js +11 -35
  95. package/out/src/adapters/wof-admin-json/adapter.js.map +1 -1
  96. package/out/src/adapters/wof-json-rows.d.ts +32 -0
  97. package/out/src/adapters/wof-json-rows.d.ts.map +1 -0
  98. package/out/src/adapters/wof-json-rows.js +45 -0
  99. package/out/src/adapters/wof-json-rows.js.map +1 -0
  100. package/out/src/adapters/wof-postalcode-json/adapter.d.ts +4 -9
  101. package/out/src/adapters/wof-postalcode-json/adapter.d.ts.map +1 -1
  102. package/out/src/adapters/wof-postalcode-json/adapter.js +12 -37
  103. package/out/src/adapters/wof-postalcode-json/adapter.js.map +1 -1
  104. package/out/src/build.d.ts +4 -3
  105. package/out/src/build.d.ts.map +1 -1
  106. package/out/src/build.js +7 -4
  107. package/out/src/build.js.map +1 -1
  108. package/out/src/index.d.ts +1 -1
  109. package/out/src/index.d.ts.map +1 -1
  110. package/out/src/index.js +1 -1
  111. package/out/src/index.js.map +1 -1
  112. package/out/src/parquet-wrapper/reader.d.ts.map +1 -1
  113. package/out/src/parquet-wrapper/reader.js +5 -0
  114. package/out/src/parquet-wrapper/reader.js.map +1 -1
  115. package/out/src/runner.d.ts +2 -2
  116. package/out/src/runner.d.ts.map +1 -1
  117. package/out/src/runner.js +1 -1
  118. package/out/src/runner.js.map +1 -1
  119. package/out/src/shard-recipes/anchor-absorption.d.ts.map +1 -1
  120. package/out/src/shard-recipes/anchor-absorption.js +4 -5
  121. package/out/src/shard-recipes/anchor-absorption.js.map +1 -1
  122. package/out/src/shard-recipes/bare-country.d.ts +25 -0
  123. package/out/src/shard-recipes/bare-country.d.ts.map +1 -0
  124. package/out/src/shard-recipes/bare-country.js +87 -0
  125. package/out/src/shard-recipes/bare-country.js.map +1 -0
  126. package/out/src/shard-recipes/boundary-stress.d.ts.map +1 -1
  127. package/out/src/shard-recipes/boundary-stress.js +2 -2
  128. package/out/src/shard-recipes/boundary-stress.js.map +1 -1
  129. package/out/src/shard-recipes/country-balanced.d.ts.map +1 -1
  130. package/out/src/shard-recipes/country-balanced.js +6 -5
  131. package/out/src/shard-recipes/country-balanced.js.map +1 -1
  132. package/out/src/shard-recipes/cz-pcfirst-preposition.d.ts.map +1 -1
  133. package/out/src/shard-recipes/cz-pcfirst-preposition.js +28 -10
  134. package/out/src/shard-recipes/cz-pcfirst-preposition.js.map +1 -1
  135. package/out/src/shard-recipes/fr-admin-split.d.ts.map +1 -1
  136. package/out/src/shard-recipes/fr-admin-split.js +4 -3
  137. package/out/src/shard-recipes/fr-admin-split.js.map +1 -1
  138. package/out/src/shard-recipes/fr-bare-street.d.ts.map +1 -1
  139. package/out/src/shard-recipes/fr-bare-street.js +72 -11
  140. package/out/src/shard-recipes/fr-bare-street.js.map +1 -1
  141. package/out/src/shard-recipes/fr-lieudit.d.ts.map +1 -1
  142. package/out/src/shard-recipes/fr-lieudit.js +4 -3
  143. package/out/src/shard-recipes/fr-lieudit.js.map +1 -1
  144. package/out/src/shard-recipes/fr-order.d.ts.map +1 -1
  145. package/out/src/shard-recipes/fr-order.js +4 -3
  146. package/out/src/shard-recipes/fr-order.js.map +1 -1
  147. package/out/src/shard-recipes/german.d.ts.map +1 -1
  148. package/out/src/shard-recipes/german.js +3 -3
  149. package/out/src/shard-recipes/german.js.map +1 -1
  150. package/out/src/shard-recipes/house-venue.js +1 -1
  151. package/out/src/shard-recipes/house-venue.js.map +1 -1
  152. package/out/src/shard-recipes/index.d.ts.map +1 -1
  153. package/out/src/shard-recipes/index.js +6 -0
  154. package/out/src/shard-recipes/index.js.map +1 -1
  155. package/out/src/shard-recipes/intersection.d.ts.map +1 -1
  156. package/out/src/shard-recipes/intersection.js +3 -3
  157. package/out/src/shard-recipes/intersection.js.map +1 -1
  158. package/out/src/shard-recipes/locale.d.ts +1 -1
  159. package/out/src/shard-recipes/locale.d.ts.map +1 -1
  160. package/out/src/shard-recipes/locale.js +5 -4
  161. package/out/src/shard-recipes/locale.js.map +1 -1
  162. package/out/src/shard-recipes/no-street.js +1 -1
  163. package/out/src/shard-recipes/no-street.js.map +1 -1
  164. package/out/src/shard-recipes/po-box-cedex.d.ts.map +1 -1
  165. package/out/src/shard-recipes/po-box-cedex.js +2 -2
  166. package/out/src/shard-recipes/po-box-cedex.js.map +1 -1
  167. package/out/src/shard-recipes/po-box.d.ts.map +1 -1
  168. package/out/src/shard-recipes/po-box.js +1 -1
  169. package/out/src/shard-recipes/po-box.js.map +1 -1
  170. package/out/src/shard-recipes/reviewed-postcode-tail.d.ts +47 -0
  171. package/out/src/shard-recipes/reviewed-postcode-tail.d.ts.map +1 -0
  172. package/out/src/shard-recipes/reviewed-postcode-tail.js +125 -0
  173. package/out/src/shard-recipes/reviewed-postcode-tail.js.map +1 -0
  174. package/out/src/shard-recipes/scaffold.d.ts +33 -4
  175. package/out/src/shard-recipes/scaffold.d.ts.map +1 -1
  176. package/out/src/shard-recipes/scaffold.js +5 -6
  177. package/out/src/shard-recipes/scaffold.js.map +1 -1
  178. package/out/src/shard-recipes/street-affix.d.ts.map +1 -1
  179. package/out/src/shard-recipes/street-affix.js +2 -2
  180. package/out/src/shard-recipes/street-affix.js.map +1 -1
  181. package/out/src/shard-recipes/street-bare.js +3 -3
  182. package/out/src/shard-recipes/street-bare.js.map +1 -1
  183. package/out/src/shard-recipes/street.js +2 -2
  184. package/out/src/shard-recipes/street.js.map +1 -1
  185. package/out/src/shard-recipes/sub-venue-sources.d.ts +2 -2
  186. package/out/src/shard-recipes/sub-venue-sources.d.ts.map +1 -1
  187. package/out/src/shard-recipes/sub-venue-sources.js +1 -1
  188. package/out/src/shard-recipes/sub-venue-sources.js.map +1 -1
  189. package/out/src/shard-recipes/sub-venue.d.ts +1 -1
  190. package/out/src/shard-recipes/sub-venue.d.ts.map +1 -1
  191. package/out/src/shard-recipes/sub-venue.js +6 -5
  192. package/out/src/shard-recipes/sub-venue.js.map +1 -1
  193. package/out/src/shard-recipes/trailing-region.d.ts +74 -0
  194. package/out/src/shard-recipes/trailing-region.d.ts.map +1 -0
  195. package/out/src/shard-recipes/trailing-region.js +157 -0
  196. package/out/src/shard-recipes/trailing-region.js.map +1 -0
  197. package/out/src/shard-recipes/unit.d.ts.map +1 -1
  198. package/out/src/shard-recipes/unit.js +2 -2
  199. package/out/src/shard-recipes/unit.js.map +1 -1
  200. package/out/src/synthesizers/boundary-stress.d.ts +1 -1
  201. package/out/src/synthesizers/boundary-stress.d.ts.map +1 -1
  202. package/out/src/synthesizers/german.d.ts +1 -1
  203. package/out/src/synthesizers/german.d.ts.map +1 -1
  204. package/out/src/synthesizers/german.js.map +1 -1
  205. package/out/src/synthesizers/house-venue.d.ts +1 -1
  206. package/out/src/synthesizers/house-venue.d.ts.map +1 -1
  207. package/out/src/synthesizers/house-venue.js +16 -2
  208. package/out/src/synthesizers/house-venue.js.map +1 -1
  209. package/out/src/synthesizers/intersection.d.ts +1 -1
  210. package/out/src/synthesizers/intersection.d.ts.map +1 -1
  211. package/out/src/synthesizers/no-street.d.ts +1 -1
  212. package/out/src/synthesizers/no-street.d.ts.map +1 -1
  213. package/out/src/synthesizers/po-box.d.ts +1 -1
  214. package/out/src/synthesizers/po-box.d.ts.map +1 -1
  215. package/out/src/synthesizers/street.d.ts +1 -1
  216. package/out/src/synthesizers/street.d.ts.map +1 -1
  217. package/out/src/synthesizers/street.js +3 -2
  218. package/out/src/synthesizers/street.js.map +1 -1
  219. package/out/src/synthesizers/utils.d.ts +1 -1
  220. package/out/src/synthesizers/utils.d.ts.map +1 -1
  221. package/out/src/synthesizers/utils.js +3 -2
  222. package/out/src/synthesizers/utils.js.map +1 -1
  223. package/out/src/tools/align-shard.d.ts.map +1 -1
  224. package/out/src/tools/align-shard.js +2 -2
  225. package/out/src/tools/align-shard.js.map +1 -1
  226. package/out/src/tools/fetch/ban.d.ts.map +1 -1
  227. package/out/src/tools/fetch/ban.js +2 -18
  228. package/out/src/tools/fetch/ban.js.map +1 -1
  229. package/out/src/tools/fetch/download.d.ts +12 -3
  230. package/out/src/tools/fetch/download.d.ts.map +1 -1
  231. package/out/src/tools/fetch/download.js +20 -4
  232. package/out/src/tools/fetch/download.js.map +1 -1
  233. package/out/src/tools/fetch/geonames-dump.d.ts +87 -0
  234. package/out/src/tools/fetch/geonames-dump.d.ts.map +1 -0
  235. package/out/src/tools/fetch/geonames-dump.js +178 -0
  236. package/out/src/tools/fetch/geonames-dump.js.map +1 -0
  237. package/out/src/tools/fetch/geonames-postal.d.ts +76 -0
  238. package/out/src/tools/fetch/geonames-postal.d.ts.map +1 -0
  239. package/out/src/tools/fetch/geonames-postal.js +125 -0
  240. package/out/src/tools/fetch/geonames-postal.js.map +1 -0
  241. package/out/src/tools/fetch/imls-pls.d.ts.map +1 -1
  242. package/out/src/tools/fetch/imls-pls.js +2 -2
  243. package/out/src/tools/fetch/imls-pls.js.map +1 -1
  244. package/out/src/tools/fetch/index.d.ts +11 -0
  245. package/out/src/tools/fetch/index.d.ts.map +1 -1
  246. package/out/src/tools/fetch/index.js +11 -0
  247. package/out/src/tools/fetch/index.js.map +1 -1
  248. package/out/src/tools/fetch/nad.d.ts.map +1 -1
  249. package/out/src/tools/fetch/nad.js +20 -11
  250. package/out/src/tools/fetch/nad.js.map +1 -1
  251. package/out/src/tools/fetch/nppes.d.ts.map +1 -1
  252. package/out/src/tools/fetch/nppes.js +9 -7
  253. package/out/src/tools/fetch/nppes.js.map +1 -1
  254. package/out/src/tools/fetch/openaddresses.d.ts.map +1 -1
  255. package/out/src/tools/fetch/openaddresses.js +18 -17
  256. package/out/src/tools/fetch/openaddresses.js.map +1 -1
  257. package/out/src/tools/fetch/ourairports.d.ts.map +1 -1
  258. package/out/src/tools/fetch/ourairports.js +7 -2
  259. package/out/src/tools/fetch/ourairports.js.map +1 -1
  260. package/out/src/tools/fetch/ppd.d.ts +0 -4
  261. package/out/src/tools/fetch/ppd.d.ts.map +1 -1
  262. package/out/src/tools/fetch/ppd.js +1 -1
  263. package/out/src/tools/fetch/ppd.js.map +1 -1
  264. package/out/src/tools/fetch/state-hi-schools.d.ts.map +1 -1
  265. package/out/src/tools/fetch/state-hi-schools.js +3 -19
  266. package/out/src/tools/fetch/state-hi-schools.js.map +1 -1
  267. package/out/src/tools/fetch/state-sources.d.ts +4 -0
  268. package/out/src/tools/fetch/state-sources.d.ts.map +1 -1
  269. package/out/src/tools/fetch/state-sources.js +1 -5
  270. package/out/src/tools/fetch/state-sources.js.map +1 -1
  271. package/out/src/tools/fetch/tiger-full.d.ts.map +1 -1
  272. package/out/src/tools/fetch/tiger-full.js +15 -21
  273. package/out/src/tools/fetch/tiger-full.js.map +1 -1
  274. package/out/src/tools/golden-expand.d.ts.map +1 -1
  275. package/out/src/tools/golden-expand.js +34 -25
  276. package/out/src/tools/golden-expand.js.map +1 -1
  277. package/out/src/tools/golden-relabel-street.js +2 -2
  278. package/out/src/tools/golden-relabel-street.js.map +1 -1
  279. package/out/src/tools/index.d.ts +2 -2
  280. package/out/src/tools/index.d.ts.map +1 -1
  281. package/out/src/tools/index.js +2 -2
  282. package/out/src/tools/index.js.map +1 -1
  283. package/out/src/tools/ingest-csv.d.ts.map +1 -1
  284. package/out/src/tools/ingest-csv.js +0 -11
  285. package/out/src/tools/ingest-csv.js.map +1 -1
  286. package/out/src/tools/overlay-manifest.d.ts +4 -0
  287. package/out/src/tools/overlay-manifest.d.ts.map +1 -1
  288. package/out/src/tools/overlay-manifest.js +16 -6
  289. package/out/src/tools/overlay-manifest.js.map +1 -1
  290. package/out/src/tools/postcode-triples.d.ts +175 -0
  291. package/out/src/tools/postcode-triples.d.ts.map +1 -0
  292. package/out/src/tools/postcode-triples.js +304 -0
  293. package/out/src/tools/postcode-triples.js.map +1 -0
  294. package/out/src/tools/shard-kryptonite.d.ts.map +1 -1
  295. package/out/src/tools/shard-kryptonite.js +1 -2
  296. package/out/src/tools/shard-kryptonite.js.map +1 -1
  297. package/out/src/tools/shard-translit.d.ts.map +1 -1
  298. package/out/src/tools/shard-translit.js +4 -26
  299. package/out/src/tools/shard-translit.js.map +1 -1
  300. package/out/src/tools/sub-venue/harvest.d.ts +100 -0
  301. package/out/src/tools/sub-venue/harvest.d.ts.map +1 -0
  302. package/out/src/tools/sub-venue/harvest.js +168 -0
  303. package/out/src/tools/sub-venue/harvest.js.map +1 -0
  304. package/out/src/tools/sub-venue/head-nouns.d.ts +50 -0
  305. package/out/src/tools/sub-venue/head-nouns.d.ts.map +1 -0
  306. package/out/src/tools/sub-venue/head-nouns.js +210 -0
  307. package/out/src/tools/sub-venue/head-nouns.js.map +1 -0
  308. package/out/src/tools/sub-venue/surfaces.d.ts +45 -0
  309. package/out/src/tools/sub-venue/surfaces.d.ts.map +1 -0
  310. package/out/src/tools/sub-venue/surfaces.js +77 -0
  311. package/out/src/tools/sub-venue/surfaces.js.map +1 -0
  312. package/out/src/tools/sub-venue/table.d.ts +229 -0
  313. package/out/src/tools/sub-venue/table.d.ts.map +1 -0
  314. package/out/src/tools/sub-venue/table.js +108 -0
  315. package/out/src/tools/sub-venue/table.js.map +1 -0
  316. package/out/src/tools/sub-venue/wikidata.d.ts +26 -0
  317. package/out/src/tools/sub-venue/wikidata.d.ts.map +1 -0
  318. package/out/src/tools/sub-venue/wikidata.js +62 -0
  319. package/out/src/tools/sub-venue/wikidata.js.map +1 -0
  320. package/out/src/tools/sub-venue-lexicon.d.ts +27 -378
  321. package/out/src/tools/sub-venue-lexicon.d.ts.map +1 -1
  322. package/out/src/tools/sub-venue-lexicon.js +30 -565
  323. package/out/src/tools/sub-venue-lexicon.js.map +1 -1
  324. package/out/src/utils/align.d.ts +1 -1
  325. package/out/src/utils/align.d.ts.map +1 -1
  326. package/out/src/utils/align.js.map +1 -1
  327. package/out/src/utils/golden.js +1 -1
  328. package/out/src/utils/golden.js.map +1 -1
  329. package/out/src/utils/license.js +1 -1
  330. package/out/src/utils/license.js.map +1 -1
  331. package/out/src/utils/parquet.d.ts +24 -5
  332. package/out/src/utils/parquet.d.ts.map +1 -1
  333. package/out/src/utils/parquet.js +6 -2
  334. package/out/src/utils/parquet.js.map +1 -1
  335. package/out/src/utils/split.d.ts +1 -1
  336. package/out/src/utils/split.d.ts.map +1 -1
  337. package/out/src/utils/split.js +2 -2
  338. package/out/src/utils/split.js.map +1 -1
  339. package/package.json +230 -10
  340. package/src/adapters/ban/adapter.ts +6 -4
  341. package/src/adapters/fcc-bdc/adapter.ts +4 -3
  342. package/src/adapters/geonames/adapter.ts +3 -2
  343. package/src/adapters/geonames-postal/adapter.ts +4 -3
  344. package/src/adapters/gnaf/adapter.ts +3 -2
  345. package/src/adapters/index.ts +2 -2
  346. package/src/adapters/openaddresses/adapter.ts +4 -3
  347. package/src/adapters/overture/adapter.ts +3 -2
  348. package/src/adapters/state-hi-schools/adapter.ts +8 -6
  349. package/src/adapters/state-ia-contractors/adapter.ts +13 -7
  350. package/src/adapters/state-ny-notaries/adapter.ts +13 -31
  351. package/src/adapters/state-tx-notaries/adapter.ts +13 -7
  352. package/src/adapters/synth-po-box/adapter.ts +5 -4
  353. package/src/adapters/tiger/adapter.ts +3 -2
  354. package/src/adapters/usgov-hrsa-fqhc/adapter.ts +8 -6
  355. package/src/adapters/usgov-imls-pls/adapter.ts +12 -7
  356. package/src/adapters/usgov-irs-bmf/adapter.ts +7 -5
  357. package/src/adapters/usgov-nad/adapter.ts +9 -8
  358. package/src/adapters/usgov-nppes/adapter.ts +13 -11
  359. package/src/adapters/usgov-samhsa-treatment-locator/adapter.ts +8 -6
  360. package/src/adapters/utils/index.ts +16 -3
  361. package/src/adapters/wof-admin-jp/adapter.ts +9 -12
  362. package/src/adapters/wof-admin-json/adapter.ts +16 -54
  363. package/src/adapters/wof-json-rows.ts +79 -0
  364. package/src/adapters/wof-postalcode-json/adapter.ts +17 -50
  365. package/src/build.ts +10 -10
  366. package/src/index.ts +1 -1
  367. package/src/parquet-wrapper/reader.ts +9 -0
  368. package/src/runner.ts +2 -7
  369. package/src/shard-recipes/anchor-absorption.ts +5 -5
  370. package/src/shard-recipes/bare-country.ts +95 -0
  371. package/src/shard-recipes/boundary-stress.ts +2 -5
  372. package/src/shard-recipes/country-balanced.ts +8 -6
  373. package/src/shard-recipes/cz-pcfirst-preposition.ts +29 -10
  374. package/src/shard-recipes/fr-admin-split.ts +6 -4
  375. package/src/shard-recipes/fr-bare-street.ts +85 -10
  376. package/src/shard-recipes/fr-lieudit.ts +6 -4
  377. package/src/shard-recipes/fr-order.ts +6 -4
  378. package/src/shard-recipes/german.ts +4 -3
  379. package/src/shard-recipes/house-venue.ts +1 -1
  380. package/src/shard-recipes/index.ts +6 -0
  381. package/src/shard-recipes/intersection.ts +5 -4
  382. package/src/shard-recipes/locale.ts +6 -8
  383. package/src/shard-recipes/no-street.ts +1 -1
  384. package/src/shard-recipes/po-box-cedex.ts +4 -3
  385. package/src/shard-recipes/po-box.ts +1 -5
  386. package/src/shard-recipes/reviewed-postcode-tail.ts +189 -0
  387. package/src/shard-recipes/scaffold.ts +38 -7
  388. package/src/shard-recipes/street-affix.ts +4 -3
  389. package/src/shard-recipes/street-bare.ts +3 -3
  390. package/src/shard-recipes/street.ts +2 -2
  391. package/src/shard-recipes/sub-venue-sources.ts +4 -14
  392. package/src/shard-recipes/sub-venue.ts +10 -8
  393. package/src/shard-recipes/trailing-region.ts +183 -0
  394. package/src/shard-recipes/unit.ts +4 -3
  395. package/src/synthesizers/boundary-stress.ts +1 -1
  396. package/src/synthesizers/german.ts +2 -1
  397. package/src/synthesizers/house-venue.ts +17 -3
  398. package/src/synthesizers/intersection.ts +1 -1
  399. package/src/synthesizers/no-street.ts +1 -1
  400. package/src/synthesizers/po-box.ts +1 -1
  401. package/src/synthesizers/street.ts +5 -3
  402. package/src/synthesizers/utils.ts +5 -3
  403. package/src/tools/align-shard.ts +3 -2
  404. package/src/tools/fetch/ban.ts +2 -22
  405. package/src/tools/fetch/download.ts +22 -4
  406. package/src/tools/fetch/geonames-dump.ts +267 -0
  407. package/src/tools/fetch/geonames-postal.ts +180 -0
  408. package/src/tools/fetch/imls-pls.ts +2 -2
  409. package/src/tools/fetch/index.ts +11 -0
  410. package/src/tools/fetch/nad.ts +21 -10
  411. package/src/tools/fetch/nppes.ts +8 -6
  412. package/src/tools/fetch/openaddresses.ts +18 -22
  413. package/src/tools/fetch/ourairports.ts +7 -2
  414. package/src/tools/fetch/ppd.ts +1 -1
  415. package/src/tools/fetch/state-hi-schools.ts +3 -23
  416. package/src/tools/fetch/state-sources.ts +1 -1
  417. package/src/tools/fetch/tiger-full.ts +17 -24
  418. package/src/tools/golden-expand.ts +44 -33
  419. package/src/tools/golden-relabel-street.ts +2 -2
  420. package/src/tools/index.ts +2 -2
  421. package/src/tools/ingest-csv.ts +0 -13
  422. package/src/tools/overlay-manifest.ts +20 -8
  423. package/src/tools/postcode-triples.ts +375 -0
  424. package/src/tools/shard-kryptonite.ts +5 -4
  425. package/src/tools/shard-translit.ts +10 -35
  426. package/src/tools/sub-venue/harvest.ts +235 -0
  427. package/src/tools/sub-venue/head-nouns.ts +242 -0
  428. package/src/tools/sub-venue/surfaces.ts +95 -0
  429. package/src/tools/sub-venue/table.ts +281 -0
  430. package/src/tools/sub-venue/wikidata.ts +85 -0
  431. package/src/tools/sub-venue-lexicon.ts +67 -886
  432. package/src/utils/align.ts +2 -1
  433. package/src/utils/golden.ts +1 -1
  434. package/src/utils/license.ts +1 -1
  435. package/src/utils/parquet.ts +22 -8
  436. package/src/utils/split.ts +4 -3
@@ -39,6 +39,7 @@
39
39
  import { mkdirSync } from "node:fs"
40
40
  import { join } from "node:path"
41
41
 
42
+ import { APIClient } from "@mailwoman/core/api"
42
43
  import { sha256File } from "@mailwoman/core/utils"
43
44
 
44
45
  import type { BaseFetchOptions, FetchSummary } from "./download.ts"
@@ -92,9 +93,13 @@ interface OurAirportsManifest {
92
93
  */
93
94
  async function readLastModified(url: string): Promise<string | null> {
94
95
  try {
95
- const res = await fetch(url, { method: "HEAD", signal: AbortSignal.timeout(30_000) })
96
+ const res = await new APIClient({ displayName: "ourairports", retry: true }).fetch({
97
+ url,
98
+ method: "head",
99
+ timeout: 30_000,
100
+ })
96
101
 
97
- return res.ok ? res.headers.get("last-modified") : null
102
+ return (res.headers["last-modified"] as string | undefined) ?? null
98
103
  } catch {
99
104
  return null
100
105
  }
@@ -104,7 +104,7 @@ export async function extractPPDTuples(
104
104
  /**
105
105
  * Stream `inputPath` (PPD CSV) → `outputPath` (OA-shaped tuples CSV), returning the row-count stats.
106
106
  */
107
- export async function runPPDExtract(inputPath: string, outputPath: string): Promise<PPDExtractStats> {
107
+ async function runPPDExtract(inputPath: string, outputPath: string): Promise<PPDExtractStats> {
108
108
  // No `encoding` — CSVSpliterator delimits raw bytes and decodes utf-8 itself (see readTuples in
109
109
  // shard-recipes/locale.ts). `header: false` yields every row as data — PPD ships no header row.
110
110
  const rows = CSVSpliterator.fromAsync<string[]>(createReadStream(inputPath), {
@@ -25,6 +25,7 @@ import { existsSync, mkdirSync, statSync } from "node:fs"
25
25
  import { unlink } from "node:fs/promises"
26
26
  import { join } from "node:path"
27
27
 
28
+ import { BYTES_PER_KIB, ByteFormatter } from "@mailwoman/core/fs/utils"
28
29
  import { sha256File } from "@mailwoman/core/utils"
29
30
 
30
31
  import type { BaseFetchOptions, FetchSummary } from "./download.ts"
@@ -34,7 +35,6 @@ import { downloadToFile, readManifest, writeManifest } from "./download.ts"
34
35
  * Bytes per KiB — the divisor for human-readable sizes, and the floor below which a "download" is an error page rather
35
36
  * than data.
36
37
  */
37
- const BYTES_PER_KIB = 1024
38
38
 
39
39
  const SOURCE_URL = "https://www.hawaiipublicschools.org/DOE%20Forms/SchoolList.xlsx"
40
40
  const SLUG = "state-hi-schools"
@@ -96,26 +96,6 @@ interface Manifest {
96
96
  notes: string
97
97
  }
98
98
 
99
- /**
100
- * Mimic `numfmt --to=iec` for a friendly byte-size log line.
101
- */
102
- function iec(bytes: number): string {
103
- if (bytes < BYTES_PER_KIB) return String(bytes)
104
- const units = ["K", "M", "G", "T", "P"]
105
- let value = bytes / 1024
106
- let i = 0
107
-
108
- while (value >= BYTES_PER_KIB && i < units.length - 1) {
109
- value /= 1024
110
-
111
- i++
112
- }
113
-
114
- const rounded = value < 10 ? value.toFixed(1) : Math.round(value).toString()
115
-
116
- return `${rounded}${units[i] ?? ""}`
117
- }
118
-
119
99
  /**
120
100
  * Run the openpyxl converter. Its stderr narration streams straight through to the process stderr (matching the old
121
101
  * `stdio: inherit` behavior) rather than routing through `report` — the python child owns those lines.
@@ -190,7 +170,7 @@ export async function fetchStateHISchools(
190
170
  }
191
171
 
192
172
  const xlsxSize = statSync(xlsxDest).size
193
- report?.(` Downloaded XLSX: ${iec(xlsxSize)}`)
173
+ report?.(` Downloaded XLSX: ${ByteFormatter.formatIEC(xlsxSize)}`)
194
174
 
195
175
  if (xlsxSize < BYTES_PER_KIB) {
196
176
  report?.(` ✗ Response too small (${xlsxSize} bytes) — probable error page`)
@@ -221,7 +201,7 @@ export async function fetchStateHISchools(
221
201
 
222
202
  await writeManifest(manifestPath, manifest)
223
203
 
224
- report?.(` ✓ ${iec(csvSize)} sha256=${csvSha}`)
204
+ report?.(` ✓ ${ByteFormatter.formatIEC(csvSize)} sha256=${csvSha}`)
225
205
  report?.(` MANIFEST written to ${manifestPath}`)
226
206
 
227
207
  return { fetched: 1, skipped: 0, failed: 0, failedCodes: [] }
@@ -20,6 +20,7 @@
20
20
  import { mkdirSync } from "node:fs"
21
21
  import { join } from "node:path"
22
22
 
23
+ import { BYTES_PER_KIB } from "@mailwoman/core/fs/utils"
23
24
  import { sha256File } from "@mailwoman/core/utils"
24
25
 
25
26
  import type { BaseFetchOptions, FetchSummary } from "./download.ts"
@@ -29,7 +30,6 @@ import { downloadToFile, writeManifest } from "./download.ts"
29
30
  * Bytes per KiB — the divisor for human-readable sizes, and the floor below which a "download" is an error page rather
30
31
  * than data.
31
32
  */
32
- const BYTES_PER_KIB = 1024
33
33
 
34
34
  export type FetchStateSourcesOptions = BaseFetchOptions
35
35
 
@@ -28,6 +28,8 @@ import { Readable } from "node:stream"
28
28
  import { pipeline } from "node:stream/promises"
29
29
  import { setTimeout as sleep } from "node:timers/promises"
30
30
 
31
+ import { APIClient, pluckResponseData } from "@mailwoman/core/api"
32
+ import { BYTES_PER_KIB, ByteFormatter } from "@mailwoman/core/fs/utils"
31
33
  import { sha256File } from "@mailwoman/core/utils"
32
34
 
33
35
  import type { BaseFetchOptions, FetchSummary } from "./download.ts"
@@ -47,8 +49,6 @@ const HTTP_OK = 200
47
49
  */
48
50
  const HTTP_REDIRECT = 300
49
51
 
50
- const BYTES_PER_KIB = 1024
51
-
52
52
  const TIGER_BASE_URL = "https://www2.census.gov/geo/tiger/TIGER2024/ADDRFEAT"
53
53
 
54
54
  export interface FetchTigerFullOptions extends BaseFetchOptions {
@@ -77,20 +77,6 @@ interface CountyEntry {
77
77
  bytes: number
78
78
  }
79
79
 
80
- function humanBytes(bytes: number): string {
81
- const units = ["B", "KiB", "MiB", "GiB", "TiB"]
82
- let value = bytes
83
- let unit = 0
84
-
85
- while (value >= BYTES_PER_KIB && unit < units.length - 1) {
86
- value /= 1024
87
-
88
- unit++
89
- }
90
-
91
- return `${value.toFixed(unit === 0 ? 0 : 1)}${units[unit]}`
92
- }
93
-
94
80
  /**
95
81
  * Stream an HTTP download to disk, returning the final HTTP status (0 on network error after retries).
96
82
  *
@@ -193,7 +179,7 @@ export async function fetchTigerFull(
193
179
  options: FetchTigerFullOptions,
194
180
  report?: (line: string) => void
195
181
  ): Promise<FetchSummary> {
196
- const skipStateFips = (options.skipStateFips ?? "50").split(/\s+/).filter(Boolean)
182
+ const skipStateFips = (options.skipStateFips ?? "50").split(/\s+/).filter((value) => value.length > 0)
197
183
  const rateSleepMs = Math.round((options.rateSleep ?? 0.2) * 1000)
198
184
  const maxParallel = options.maxParallel ?? 4
199
185
  const dryRun = options.dryRun ?? false
@@ -205,13 +191,17 @@ export async function fetchTigerFull(
205
191
 
206
192
  report?.(`=== Fetching TIGER 2024 ADDRFEAT directory listing...`)
207
193
 
208
- const listingRes = await fetch(`${TIGER_BASE_URL}/`, {
209
- headers: { "Accept-Encoding": "gzip, br" },
210
- signal: AbortSignal.timeout(60_000),
194
+ // `responseType: "text"` — an Apache directory index, scraped below. The per-county ARCHIVE downloads
195
+ // stay on raw `fetch` (they stream to disk; see `downloadOne`).
196
+ const listingRes = await new APIClient({
197
+ displayName: "tiger-listing",
198
+ retry: true,
199
+ axios: { headers: { "Accept-Encoding": "gzip, br" } },
211
200
  })
201
+ .fetch<string>({ url: `${TIGER_BASE_URL}/`, responseType: "text", timeout: 60_000 })
202
+ .then(pluckResponseData)
212
203
 
213
- if (!listingRes.ok) throw new Error(`Failed to fetch TIGER directory listing: HTTP ${listingRes.status}`)
214
- const html = await listingRes.text()
204
+ const html = listingRes
215
205
  const allZips = [...new Set(html.match(/tl_2024_[0-9]{5}_addrfeat\.zip/g))].toSorted()
216
206
  const totalCounties = allZips.length
217
207
  report?.(` Found ${totalCounties} county ZIPs in the TIGER 2024 ADDRFEAT index.`)
@@ -314,7 +304,10 @@ export async function fetchTigerFull(
314
304
  // Collect results from this state.
315
305
  for (const result of results) {
316
306
  if (result.ok) {
317
- report?.(` ok ${result.filename} ${humanBytes(result.bytes)} sha256=${result.sha256.slice(0, 12)}...`)
307
+ report?.(
308
+ ` ok ${result.filename} ${ByteFormatter.formatIEC(result.bytes)} sha256=${result.sha256.slice(0, 12)}...`
309
+ )
310
+
318
311
  manifest.set(result.filename, { filename: result.filename, sha256: result.sha256, bytes: result.bytes })
319
312
 
320
313
  totalFetched++
@@ -350,7 +343,7 @@ export async function fetchTigerFull(
350
343
  report?.(` Counties failed : ${totalFailed}`)
351
344
 
352
345
  if (totalBytesFetched > 0) {
353
- report?.(` Bytes fetched this run : ${humanBytes(totalBytesFetched)} (${totalBytesFetched})`)
346
+ report?.(` Bytes fetched this run : ${ByteFormatter.formatIEC(totalBytesFetched)} (${totalBytesFetched})`)
354
347
  }
355
348
 
356
349
  if (totalFailed > 0) {
@@ -50,8 +50,9 @@ import { mkdir } from "node:fs/promises"
50
50
  import { dirname } from "node:path"
51
51
 
52
52
  import { ParquetReader } from "@dsnp/parquetjs"
53
+ import { APIClient, pluckResponseData } from "@mailwoman/core/api"
53
54
  import { $private } from "@mailwoman/core/env"
54
- import { tryParsingJSON } from "@mailwoman/core/objects"
55
+ import { isPresent, tryParsingJSON } from "@mailwoman/core/objects"
55
56
  import { dataRootPath } from "@mailwoman/core/utils"
56
57
  import { createNewlineWriter } from "spliterator"
57
58
 
@@ -195,7 +196,7 @@ async function loadSeeds(
195
196
  const paths = corpusPath
196
197
  .split(",")
197
198
  .map((p) => p.trim())
198
- .filter(Boolean)
199
+ .filter(isPresent)
199
200
 
200
201
  report?.(`reading seeds from ${paths.length} shard(s) (target: ${count}, stratified)`)
201
202
 
@@ -345,24 +346,28 @@ function makeDeepseekProvider(model: string): LlmProvider {
345
346
  name: "deepseek",
346
347
  model,
347
348
  async generateVariants(seed, n) {
348
- const res = await fetch("https://api.deepseek.com/chat/completions", {
349
- method: "POST",
350
- headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
351
- body: JSON.stringify({
352
- model,
353
- messages: [
354
- { role: "system", content: SYSTEM_PROMPT },
355
- { role: "user", content: buildUserPrompt(seed, n) },
356
- ],
357
- response_format: { type: "json_object" },
358
- max_tokens: 800,
359
- temperature: 0.7,
360
- }),
361
- signal: AbortSignal.timeout(60_000),
349
+ const data = await new APIClient({
350
+ displayName: "deepseek",
351
+ retry: true,
352
+ axios: { headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" } },
362
353
  })
354
+ .fetch<{ choices?: Array<{ message: { content: string } }> }>({
355
+ url: "https://api.deepseek.com/chat/completions",
356
+ method: "post",
357
+ timeout: 60_000,
358
+ data: {
359
+ model,
360
+ messages: [
361
+ { role: "system", content: SYSTEM_PROMPT },
362
+ { role: "user", content: buildUserPrompt(seed, n) },
363
+ ],
364
+ response_format: { type: "json_object" },
365
+ max_tokens: 800,
366
+ temperature: 0.7,
367
+ },
368
+ })
369
+ .then(pluckResponseData)
363
370
 
364
- if (!res.ok) throw new Error(`DeepSeek HTTP ${res.status}: ${await res.text()}`)
365
- const data = (await res.json()) as { choices?: Array<{ message: { content: string } }> }
366
371
  const content = data.choices?.[0]?.message.content ?? "{}"
367
372
 
368
373
  return parseCandidates(content)
@@ -379,24 +384,30 @@ function makeAnthropicProvider(model: string): LlmProvider {
379
384
  name: "anthropic",
380
385
  model,
381
386
  async generateVariants(seed, n) {
382
- const res = await fetch("https://api.anthropic.com/v1/messages", {
383
- method: "POST",
384
- headers: {
385
- "x-api-key": apiKey,
386
- "anthropic-version": "2023-06-01",
387
- "Content-Type": "application/json",
387
+ const data = await new APIClient({
388
+ displayName: "anthropic",
389
+ retry: true,
390
+ axios: {
391
+ headers: {
392
+ "x-api-key": apiKey,
393
+ "anthropic-version": "2023-06-01",
394
+ "Content-Type": "application/json",
395
+ },
388
396
  },
389
- body: JSON.stringify({
390
- model,
391
- max_tokens: 800,
392
- system: SYSTEM_PROMPT,
393
- messages: [{ role: "user", content: buildUserPrompt(seed, n) }],
394
- }),
395
- signal: AbortSignal.timeout(60_000),
396
397
  })
398
+ .fetch<{ content?: Array<{ type: string; text: string }> }>({
399
+ url: "https://api.anthropic.com/v1/messages",
400
+ method: "post",
401
+ timeout: 60_000,
402
+ data: {
403
+ model,
404
+ max_tokens: 800,
405
+ system: SYSTEM_PROMPT,
406
+ messages: [{ role: "user", content: buildUserPrompt(seed, n) }],
407
+ },
408
+ })
409
+ .then(pluckResponseData)
397
410
 
398
- if (!res.ok) throw new Error(`Anthropic HTTP ${res.status}: ${await res.text()}`)
399
- const data = (await res.json()) as { content?: Array<{ type: string; text: string }> }
400
411
  const text = data.content?.find((c) => c.type === "text")?.text ?? "[]"
401
412
 
402
413
  return parseCandidates(text)
@@ -60,7 +60,7 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from
60
60
  import { basename, join } from "node:path"
61
61
 
62
62
  import { isStreetDirectionalToken, matchTrailingSuffix, type USStreetSuffix } from "@mailwoman/codex/us"
63
- import { parseJSONStrict, tryParsingJSON } from "@mailwoman/core/objects"
63
+ import { isPresent, parseJSONStrict, tryParsingJSON } from "@mailwoman/core/objects"
64
64
  import { sha256File } from "@mailwoman/core/utils"
65
65
  import { TextSpliterator } from "spliterator"
66
66
 
@@ -616,7 +616,7 @@ export async function relabelGoldenDirectory(
616
616
  function renderDeckMarkdown(deck: GoldenRelabelDeckEntry[], parent: string, version: string): string {
617
617
  const span = (components: Record<string, string>): string =>
618
618
  [components.street_prefix, components.street, components.street_suffix]
619
- .filter(Boolean)
619
+ .filter(isPresent)
620
620
  .map((s) => JSON.stringify(s))
621
621
  .join(" + ")
622
622
 
@@ -4,8 +4,7 @@
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
6
  * Corpus operator tools — the `run()`-style modules behind `mailwoman corpus …` commands. No argv,
7
- * no `process.exit`: commands own parsing, rendering, and exit codes (see the 2026-07-09
8
- * scripts→Pastel spec).
7
+ * no `process.exit`: commands own parsing, rendering, and exit codes.
9
8
  */
10
9
 
11
10
  export * from "./align-shard.ts"
@@ -23,6 +22,7 @@ export * from "./lint-shard.ts"
23
22
  export * from "./lint-shard-vocab.ts"
24
23
  export * from "./shard-kryptonite.ts"
25
24
  export * from "./overture-subvenue.ts"
25
+ export * from "./postcode-triples.ts"
26
26
  export * from "./sub-venue-lexicon.ts"
27
27
  export * from "./sub-venue-promotions.ts"
28
28
  export * from "./shard-translit.ts"
@@ -241,7 +241,6 @@ async function runIngest(opts: IngestOptions): Promise<void> {
241
241
  const createTableSQL = `CREATE TABLE IF NOT EXISTS "${opts.tableName}" (\n ${colDefs}\n);`
242
242
 
243
243
  const tempCols = columns.map((c) => `"${c.name}"`).join(", ")
244
- const insertSQL = `INSERT INTO "${opts.tableName}" (${tempCols})\nSELECT ${tempCols} FROM temp."${opts.tableName}_source";`
245
244
 
246
245
  process.stderr.write(`\nSchema inferred from ${sampleRows.length} sample rows:\n`)
247
246
  process.stderr.write(`${createTableSQL}\n\n`)
@@ -264,17 +263,6 @@ async function runIngest(opts: IngestOptions): Promise<void> {
264
263
 
265
264
  // Use the .import approach via a temp table, then INSERT INTO ... SELECT to handle
266
265
  // NULL normalization and type coercion.
267
- const csvBasename = basename(opts.inputPath)
268
-
269
- const importSQL = [
270
- `CREATE TEMP TABLE "${opts.tableName}_source" (${colDefs});`,
271
- `.mode csv`,
272
- `.separator "${opts.separator}"`,
273
- `.import "${csvBasename}" --skip ${opts.skipLines + (opts.hasHeader ? 1 : 0)} --schema temp ${opts.tableName}_source`,
274
- insertSQL,
275
- `DROP TABLE temp."${opts.tableName}_source";`,
276
- ]
277
-
278
266
  // better-sqlite3 doesn't support .import natively, so we use a different approach:
279
267
  // Read the CSV line-by-line and INSERT in a transaction.
280
268
  process.stderr.write(`Importing rows...\n`)
@@ -373,7 +361,6 @@ async function runIngest(opts: IngestOptions): Promise<void> {
373
361
  db.close()
374
362
 
375
363
  // Write MANIFEST
376
- const fileSize = (await import("node:fs/promises")).stat
377
364
  const stat = await (await import("node:fs/promises")).stat(opts.outputPath)
378
365
 
379
366
  const manifest = {
@@ -24,7 +24,7 @@
24
24
  */
25
25
 
26
26
  import { readFileSync, statSync, writeFileSync } from "node:fs"
27
- import { join } from "node:path"
27
+ import { basename, dirname, join } from "node:path"
28
28
 
29
29
  import { parseJSONStrict } from "@mailwoman/core/objects"
30
30
  import { sha256Hex } from "@mailwoman/core/utils"
@@ -96,6 +96,24 @@ export interface OverlayManifestOptions {
96
96
  note: string
97
97
  }
98
98
 
99
+ /**
100
+ * Resolve a base manifest's shard path to the mounted corpus tree used by Modal.
101
+ */
102
+ export function rerootBaseShardPath(path: string, baseManifestPath: string): string {
103
+ const versionedIndex = path.indexOf("/corpus/versioned/")
104
+
105
+ if (versionedIndex !== -1) return "/data" + path.slice(versionedIndex)
106
+
107
+ if (/^\/data\/(?:train|val|test)\//u.test(path)) {
108
+ const localBaseDir = dirname(baseManifestPath)
109
+ const baseModalRoot = `/data/corpus/versioned/${basename(dirname(localBaseDir))}/${basename(localBaseDir)}`
110
+
111
+ return baseModalRoot + path.slice("/data".length)
112
+ }
113
+
114
+ return path
115
+ }
116
+
99
117
  export async function assembleOverlayManifest(args: OverlayManifestOptions): Promise<void> {
100
118
  const base = parseJSONStrict<BaseManifest>(readFileSync(args.base, "utf8"))
101
119
 
@@ -103,13 +121,7 @@ export async function assembleOverlayManifest(args: OverlayManifestOptions): Pro
103
121
  console.log(`WARN: base already contains source '${args.source}' — is this the right base?`)
104
122
  }
105
123
 
106
- const reroot = (p: string): string => {
107
- const i = p.indexOf("/corpus/versioned/")
108
-
109
- return i !== -1 ? "/data" + p.slice(i) : p
110
- }
111
-
112
- const kept = base.shards.map((s) => ({ ...s, path: reroot(s.path) }))
124
+ const kept = base.shards.map((s) => ({ ...s, path: rerootBaseShardPath(s.path, args.base) }))
113
125
 
114
126
  const newTrain = await descriptor(
115
127
  join(args.newDir, "train", args.shardParquet),