@mailwoman/corpus 8.0.0 → 8.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 (483) hide show
  1. package/out/src/adapter.d.ts +15 -5
  2. package/out/src/adapter.d.ts.map +1 -1
  3. package/out/src/adapter.js +11 -9
  4. package/out/src/adapter.js.map +1 -1
  5. package/out/src/adapters/ban/adapter.d.ts +7 -0
  6. package/out/src/adapters/ban/adapter.d.ts.map +1 -1
  7. package/out/src/adapters/ban/adapter.js +9 -2
  8. package/out/src/adapters/ban/adapter.js.map +1 -1
  9. package/out/src/adapters/ban/street-decompose.d.ts.map +1 -1
  10. package/out/src/adapters/ban/street-decompose.js +5 -1
  11. package/out/src/adapters/ban/street-decompose.js.map +1 -1
  12. package/out/src/adapters/fcc-bdc/adapter.d.ts +14 -1
  13. package/out/src/adapters/fcc-bdc/adapter.d.ts.map +1 -1
  14. package/out/src/adapters/fcc-bdc/adapter.js +15 -2
  15. package/out/src/adapters/fcc-bdc/adapter.js.map +1 -1
  16. package/out/src/adapters/geonames/adapter.d.ts +11 -0
  17. package/out/src/adapters/geonames/adapter.d.ts.map +1 -1
  18. package/out/src/adapters/geonames/adapter.js +24 -5
  19. package/out/src/adapters/geonames/adapter.js.map +1 -1
  20. package/out/src/adapters/geonames-postal/adapter.d.ts +11 -0
  21. package/out/src/adapters/geonames-postal/adapter.d.ts.map +1 -1
  22. package/out/src/adapters/geonames-postal/adapter.js +14 -1
  23. package/out/src/adapters/geonames-postal/adapter.js.map +1 -1
  24. package/out/src/adapters/gnaf/adapter.d.ts +10 -1
  25. package/out/src/adapters/gnaf/adapter.d.ts.map +1 -1
  26. package/out/src/adapters/gnaf/adapter.js +11 -2
  27. package/out/src/adapters/gnaf/adapter.js.map +1 -1
  28. package/out/src/adapters/gnaf/assemble.d.ts +18 -6
  29. package/out/src/adapters/gnaf/assemble.d.ts.map +1 -1
  30. package/out/src/adapters/gnaf/assemble.js +16 -6
  31. package/out/src/adapters/gnaf/assemble.js.map +1 -1
  32. package/out/src/adapters/index.d.ts.map +1 -1
  33. package/out/src/adapters/index.js.map +1 -1
  34. package/out/src/adapters/openaddresses/adapter.d.ts +11 -0
  35. package/out/src/adapters/openaddresses/adapter.d.ts.map +1 -1
  36. package/out/src/adapters/openaddresses/adapter.js +18 -3
  37. package/out/src/adapters/openaddresses/adapter.js.map +1 -1
  38. package/out/src/adapters/overture/adapter.d.ts +11 -0
  39. package/out/src/adapters/overture/adapter.d.ts.map +1 -1
  40. package/out/src/adapters/overture/adapter.js +12 -1
  41. package/out/src/adapters/overture/adapter.js.map +1 -1
  42. package/out/src/adapters/state-hi-schools/adapter.d.ts +11 -0
  43. package/out/src/adapters/state-hi-schools/adapter.d.ts.map +1 -1
  44. package/out/src/adapters/state-hi-schools/adapter.js +11 -0
  45. package/out/src/adapters/state-hi-schools/adapter.js.map +1 -1
  46. package/out/src/adapters/state-ia-contractors/adapter.d.ts +11 -0
  47. package/out/src/adapters/state-ia-contractors/adapter.d.ts.map +1 -1
  48. package/out/src/adapters/state-ia-contractors/adapter.js +11 -0
  49. package/out/src/adapters/state-ia-contractors/adapter.js.map +1 -1
  50. package/out/src/adapters/state-ny-notaries/adapter.d.ts +11 -0
  51. package/out/src/adapters/state-ny-notaries/adapter.d.ts.map +1 -1
  52. package/out/src/adapters/state-ny-notaries/adapter.js +11 -0
  53. package/out/src/adapters/state-ny-notaries/adapter.js.map +1 -1
  54. package/out/src/adapters/state-tx-notaries/adapter.d.ts +11 -0
  55. package/out/src/adapters/state-tx-notaries/adapter.d.ts.map +1 -1
  56. package/out/src/adapters/state-tx-notaries/adapter.js +15 -2
  57. package/out/src/adapters/state-tx-notaries/adapter.js.map +1 -1
  58. package/out/src/adapters/synth-po-box/adapter.d.ts +11 -0
  59. package/out/src/adapters/synth-po-box/adapter.d.ts.map +1 -1
  60. package/out/src/adapters/synth-po-box/adapter.js +13 -2
  61. package/out/src/adapters/synth-po-box/adapter.js.map +1 -1
  62. package/out/src/adapters/tiger/adapter.d.ts +14 -1
  63. package/out/src/adapters/tiger/adapter.d.ts.map +1 -1
  64. package/out/src/adapters/tiger/adapter.js +19 -4
  65. package/out/src/adapters/tiger/adapter.js.map +1 -1
  66. package/out/src/adapters/tiger/street-decompose.d.ts.map +1 -1
  67. package/out/src/adapters/tiger/street-decompose.js.map +1 -1
  68. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +11 -0
  69. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts.map +1 -1
  70. package/out/src/adapters/usgov-hrsa-fqhc/adapter.js +12 -1
  71. package/out/src/adapters/usgov-hrsa-fqhc/adapter.js.map +1 -1
  72. package/out/src/adapters/usgov-imls-pls/adapter.d.ts +11 -0
  73. package/out/src/adapters/usgov-imls-pls/adapter.d.ts.map +1 -1
  74. package/out/src/adapters/usgov-imls-pls/adapter.js +11 -0
  75. package/out/src/adapters/usgov-imls-pls/adapter.js.map +1 -1
  76. package/out/src/adapters/usgov-irs-bmf/adapter.d.ts +11 -0
  77. package/out/src/adapters/usgov-irs-bmf/adapter.d.ts.map +1 -1
  78. package/out/src/adapters/usgov-irs-bmf/adapter.js +17 -2
  79. package/out/src/adapters/usgov-irs-bmf/adapter.js.map +1 -1
  80. package/out/src/adapters/usgov-nad/adapter.d.ts +11 -0
  81. package/out/src/adapters/usgov-nad/adapter.d.ts.map +1 -1
  82. package/out/src/adapters/usgov-nad/adapter.js +12 -1
  83. package/out/src/adapters/usgov-nad/adapter.js.map +1 -1
  84. package/out/src/adapters/usgov-nppes/adapter.d.ts +11 -0
  85. package/out/src/adapters/usgov-nppes/adapter.d.ts.map +1 -1
  86. package/out/src/adapters/usgov-nppes/adapter.js +11 -0
  87. package/out/src/adapters/usgov-nppes/adapter.js.map +1 -1
  88. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts +11 -0
  89. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts.map +1 -1
  90. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js +15 -2
  91. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js.map +1 -1
  92. package/out/src/adapters/wof-admin-jp/adapter.d.ts +7 -0
  93. package/out/src/adapters/wof-admin-jp/adapter.d.ts.map +1 -1
  94. package/out/src/adapters/wof-admin-jp/adapter.js +18 -3
  95. package/out/src/adapters/wof-admin-jp/adapter.js.map +1 -1
  96. package/out/src/adapters/wof-admin-json/adapter.d.ts +13 -3
  97. package/out/src/adapters/wof-admin-json/adapter.d.ts.map +1 -1
  98. package/out/src/adapters/wof-admin-json/adapter.js +15 -5
  99. package/out/src/adapters/wof-admin-json/adapter.js.map +1 -1
  100. package/out/src/adapters/wof-postalcode-json/adapter.d.ts +7 -0
  101. package/out/src/adapters/wof-postalcode-json/adapter.d.ts.map +1 -1
  102. package/out/src/adapters/wof-postalcode-json/adapter.js +9 -2
  103. package/out/src/adapters/wof-postalcode-json/adapter.js.map +1 -1
  104. package/out/src/align.d.ts +12 -4
  105. package/out/src/align.d.ts.map +1 -1
  106. package/out/src/align.js +9 -5
  107. package/out/src/align.js.map +1 -1
  108. package/out/src/build.d.ts +24 -8
  109. package/out/src/build.d.ts.map +1 -1
  110. package/out/src/build.js +3 -3
  111. package/out/src/build.js.map +1 -1
  112. package/out/src/codex/us-fips-state.d.ts +6 -2
  113. package/out/src/codex/us-fips-state.d.ts.map +1 -1
  114. package/out/src/codex/us-fips-state.js +3 -1
  115. package/out/src/codex/us-fips-state.js.map +1 -1
  116. package/out/src/golden.d.ts +21 -7
  117. package/out/src/golden.d.ts.map +1 -1
  118. package/out/src/golden.js +18 -10
  119. package/out/src/golden.js.map +1 -1
  120. package/out/src/license.d.ts +3 -1
  121. package/out/src/license.d.ts.map +1 -1
  122. package/out/src/license.js +4 -2
  123. package/out/src/license.js.map +1 -1
  124. package/out/src/parquet-wrapper/reader.d.ts +4 -2
  125. package/out/src/parquet-wrapper/reader.d.ts.map +1 -1
  126. package/out/src/parquet-wrapper/reader.js +5 -4
  127. package/out/src/parquet-wrapper/reader.js.map +1 -1
  128. package/out/src/parquet-wrapper/schema.d.ts +14 -10
  129. package/out/src/parquet-wrapper/schema.d.ts.map +1 -1
  130. package/out/src/parquet-wrapper/schema.js +6 -2
  131. package/out/src/parquet-wrapper/schema.js.map +1 -1
  132. package/out/src/parquet-wrapper/writer.d.ts +12 -4
  133. package/out/src/parquet-wrapper/writer.d.ts.map +1 -1
  134. package/out/src/parquet-wrapper/writer.js +12 -4
  135. package/out/src/parquet-wrapper/writer.js.map +1 -1
  136. package/out/src/parquet.d.ts +21 -7
  137. package/out/src/parquet.d.ts.map +1 -1
  138. package/out/src/parquet.js +15 -4
  139. package/out/src/parquet.js.map +1 -1
  140. package/out/src/runner.d.ts +39 -13
  141. package/out/src/runner.d.ts.map +1 -1
  142. package/out/src/runner.js +7 -3
  143. package/out/src/runner.js.map +1 -1
  144. package/out/src/shard-recipes/anchor-absorption.d.ts +4 -0
  145. package/out/src/shard-recipes/anchor-absorption.d.ts.map +1 -1
  146. package/out/src/shard-recipes/anchor-absorption.js +14 -5
  147. package/out/src/shard-recipes/anchor-absorption.js.map +1 -1
  148. package/out/src/shard-recipes/boundary-stress.d.ts +4 -0
  149. package/out/src/shard-recipes/boundary-stress.d.ts.map +1 -1
  150. package/out/src/shard-recipes/boundary-stress.js +13 -7
  151. package/out/src/shard-recipes/boundary-stress.js.map +1 -1
  152. package/out/src/shard-recipes/country-balanced.d.ts +4 -0
  153. package/out/src/shard-recipes/country-balanced.d.ts.map +1 -1
  154. package/out/src/shard-recipes/country-balanced.js +39 -11
  155. package/out/src/shard-recipes/country-balanced.js.map +1 -1
  156. package/out/src/shard-recipes/cz-pcfirst-preposition.d.ts +4 -0
  157. package/out/src/shard-recipes/cz-pcfirst-preposition.d.ts.map +1 -1
  158. package/out/src/shard-recipes/cz-pcfirst-preposition.js +4 -0
  159. package/out/src/shard-recipes/cz-pcfirst-preposition.js.map +1 -1
  160. package/out/src/shard-recipes/fr-admin-split.d.ts +4 -0
  161. package/out/src/shard-recipes/fr-admin-split.d.ts.map +1 -1
  162. package/out/src/shard-recipes/fr-admin-split.js +14 -3
  163. package/out/src/shard-recipes/fr-admin-split.js.map +1 -1
  164. package/out/src/shard-recipes/fr-bare-street.d.ts +4 -0
  165. package/out/src/shard-recipes/fr-bare-street.d.ts.map +1 -1
  166. package/out/src/shard-recipes/fr-bare-street.js +4 -0
  167. package/out/src/shard-recipes/fr-bare-street.js.map +1 -1
  168. package/out/src/shard-recipes/fr-fragment.d.ts +4 -0
  169. package/out/src/shard-recipes/fr-fragment.d.ts.map +1 -1
  170. package/out/src/shard-recipes/fr-fragment.js +25 -8
  171. package/out/src/shard-recipes/fr-fragment.js.map +1 -1
  172. package/out/src/shard-recipes/fr-lieudit.d.ts +4 -0
  173. package/out/src/shard-recipes/fr-lieudit.d.ts.map +1 -1
  174. package/out/src/shard-recipes/fr-lieudit.js +21 -8
  175. package/out/src/shard-recipes/fr-lieudit.js.map +1 -1
  176. package/out/src/shard-recipes/fr-order.d.ts +4 -0
  177. package/out/src/shard-recipes/fr-order.d.ts.map +1 -1
  178. package/out/src/shard-recipes/fr-order.js +27 -8
  179. package/out/src/shard-recipes/fr-order.js.map +1 -1
  180. package/out/src/shard-recipes/german.d.ts +4 -0
  181. package/out/src/shard-recipes/german.d.ts.map +1 -1
  182. package/out/src/shard-recipes/german.js +16 -6
  183. package/out/src/shard-recipes/german.js.map +1 -1
  184. package/out/src/shard-recipes/house-venue.d.ts +4 -0
  185. package/out/src/shard-recipes/house-venue.d.ts.map +1 -1
  186. package/out/src/shard-recipes/house-venue.js +4 -0
  187. package/out/src/shard-recipes/house-venue.js.map +1 -1
  188. package/out/src/shard-recipes/index.d.ts +9 -3
  189. package/out/src/shard-recipes/index.d.ts.map +1 -1
  190. package/out/src/shard-recipes/index.js +12 -4
  191. package/out/src/shard-recipes/index.js.map +1 -1
  192. package/out/src/shard-recipes/intersection.d.ts +4 -0
  193. package/out/src/shard-recipes/intersection.d.ts.map +1 -1
  194. package/out/src/shard-recipes/intersection.js +27 -13
  195. package/out/src/shard-recipes/intersection.js.map +1 -1
  196. package/out/src/shard-recipes/locale.d.ts +4 -0
  197. package/out/src/shard-recipes/locale.d.ts.map +1 -1
  198. package/out/src/shard-recipes/locale.js +9 -4
  199. package/out/src/shard-recipes/locale.js.map +1 -1
  200. package/out/src/shard-recipes/nl-postcode.d.ts +4 -0
  201. package/out/src/shard-recipes/nl-postcode.d.ts.map +1 -1
  202. package/out/src/shard-recipes/nl-postcode.js +8 -2
  203. package/out/src/shard-recipes/nl-postcode.js.map +1 -1
  204. package/out/src/shard-recipes/no-fragment.d.ts +4 -0
  205. package/out/src/shard-recipes/no-fragment.d.ts.map +1 -1
  206. package/out/src/shard-recipes/no-fragment.js +8 -2
  207. package/out/src/shard-recipes/no-fragment.js.map +1 -1
  208. package/out/src/shard-recipes/no-street-led.d.ts +4 -0
  209. package/out/src/shard-recipes/no-street-led.d.ts.map +1 -1
  210. package/out/src/shard-recipes/no-street-led.js +5 -1
  211. package/out/src/shard-recipes/no-street-led.js.map +1 -1
  212. package/out/src/shard-recipes/no-street.d.ts +4 -0
  213. package/out/src/shard-recipes/no-street.d.ts.map +1 -1
  214. package/out/src/shard-recipes/no-street.js +4 -0
  215. package/out/src/shard-recipes/no-street.js.map +1 -1
  216. package/out/src/shard-recipes/po-box-cedex.d.ts +4 -0
  217. package/out/src/shard-recipes/po-box-cedex.d.ts.map +1 -1
  218. package/out/src/shard-recipes/po-box-cedex.js +99 -43
  219. package/out/src/shard-recipes/po-box-cedex.js.map +1 -1
  220. package/out/src/shard-recipes/po-box.d.ts +4 -0
  221. package/out/src/shard-recipes/po-box.d.ts.map +1 -1
  222. package/out/src/shard-recipes/po-box.js +4 -0
  223. package/out/src/shard-recipes/po-box.js.map +1 -1
  224. package/out/src/shard-recipes/scaffold.d.ts +48 -16
  225. package/out/src/shard-recipes/scaffold.d.ts.map +1 -1
  226. package/out/src/shard-recipes/scaffold.js +10 -6
  227. package/out/src/shard-recipes/scaffold.js.map +1 -1
  228. package/out/src/shard-recipes/si-bare-village.d.ts +4 -0
  229. package/out/src/shard-recipes/si-bare-village.d.ts.map +1 -1
  230. package/out/src/shard-recipes/si-bare-village.js +4 -0
  231. package/out/src/shard-recipes/si-bare-village.js.map +1 -1
  232. package/out/src/shard-recipes/street-affix.d.ts +4 -0
  233. package/out/src/shard-recipes/street-affix.d.ts.map +1 -1
  234. package/out/src/shard-recipes/street-affix.js +29 -10
  235. package/out/src/shard-recipes/street-affix.js.map +1 -1
  236. package/out/src/shard-recipes/street-bare.d.ts +4 -0
  237. package/out/src/shard-recipes/street-bare.d.ts.map +1 -1
  238. package/out/src/shard-recipes/street-bare.js +4 -0
  239. package/out/src/shard-recipes/street-bare.js.map +1 -1
  240. package/out/src/shard-recipes/street.d.ts +4 -0
  241. package/out/src/shard-recipes/street.d.ts.map +1 -1
  242. package/out/src/shard-recipes/street.js +4 -0
  243. package/out/src/shard-recipes/street.js.map +1 -1
  244. package/out/src/shard-recipes/unit.d.ts +4 -0
  245. package/out/src/shard-recipes/unit.d.ts.map +1 -1
  246. package/out/src/shard-recipes/unit.js +45 -14
  247. package/out/src/shard-recipes/unit.js.map +1 -1
  248. package/out/src/split.d.ts +18 -6
  249. package/out/src/split.d.ts.map +1 -1
  250. package/out/src/split.js +4 -2
  251. package/out/src/split.js.map +1 -1
  252. package/out/src/synthesize-anchor-absorption.d.ts +7 -1
  253. package/out/src/synthesize-anchor-absorption.d.ts.map +1 -1
  254. package/out/src/synthesize-anchor-absorption.js +28 -14
  255. package/out/src/synthesize-anchor-absorption.js.map +1 -1
  256. package/out/src/synthesize-boundary-stress.d.ts +3 -1
  257. package/out/src/synthesize-boundary-stress.d.ts.map +1 -1
  258. package/out/src/synthesize-boundary-stress.js +35 -28
  259. package/out/src/synthesize-boundary-stress.js.map +1 -1
  260. package/out/src/synthesize-german.d.ts +15 -5
  261. package/out/src/synthesize-german.d.ts.map +1 -1
  262. package/out/src/synthesize-german.js +9 -3
  263. package/out/src/synthesize-german.js.map +1 -1
  264. package/out/src/synthesize-house-venue.d.ts.map +1 -1
  265. package/out/src/synthesize-house-venue.js +15 -15
  266. package/out/src/synthesize-house-venue.js.map +1 -1
  267. package/out/src/synthesize-intersection.d.ts +9 -3
  268. package/out/src/synthesize-intersection.d.ts.map +1 -1
  269. package/out/src/synthesize-intersection.js +25 -6
  270. package/out/src/synthesize-intersection.js.map +1 -1
  271. package/out/src/synthesize-no-street.d.ts +3 -1
  272. package/out/src/synthesize-no-street.d.ts.map +1 -1
  273. package/out/src/synthesize-no-street.js +5 -6
  274. package/out/src/synthesize-no-street.js.map +1 -1
  275. package/out/src/synthesize-po-box.d.ts +15 -5
  276. package/out/src/synthesize-po-box.d.ts.map +1 -1
  277. package/out/src/synthesize-po-box.js +21 -7
  278. package/out/src/synthesize-po-box.js.map +1 -1
  279. package/out/src/synthesize-street.d.ts +3 -1
  280. package/out/src/synthesize-street.d.ts.map +1 -1
  281. package/out/src/synthesize-street.js +6 -1
  282. package/out/src/synthesize-street.js.map +1 -1
  283. package/out/src/synthesize.d.ts +39 -13
  284. package/out/src/synthesize.d.ts.map +1 -1
  285. package/out/src/synthesize.js +66 -36
  286. package/out/src/synthesize.js.map +1 -1
  287. package/out/src/tokenize.d.ts +15 -5
  288. package/out/src/tokenize.d.ts.map +1 -1
  289. package/out/src/tokenize.js.map +1 -1
  290. package/out/src/tools/align-shard.d.ts.map +1 -1
  291. package/out/src/tools/align-shard.js +3 -1
  292. package/out/src/tools/align-shard.js.map +1 -1
  293. package/out/src/tools/audit.d.ts.map +1 -1
  294. package/out/src/tools/audit.js +20 -8
  295. package/out/src/tools/audit.js.map +1 -1
  296. package/out/src/tools/corpus-stats.d.ts.map +1 -1
  297. package/out/src/tools/corpus-stats.js.map +1 -1
  298. package/out/src/tools/fetch/ban.d.ts.map +1 -1
  299. package/out/src/tools/fetch/ban.js +17 -10
  300. package/out/src/tools/fetch/ban.js.map +1 -1
  301. package/out/src/tools/fetch/download.d.ts +30 -10
  302. package/out/src/tools/fetch/download.d.ts.map +1 -1
  303. package/out/src/tools/fetch/download.js +26 -6
  304. package/out/src/tools/fetch/download.js.map +1 -1
  305. package/out/src/tools/fetch/hrsa.d.ts.map +1 -1
  306. package/out/src/tools/fetch/hrsa.js.map +1 -1
  307. package/out/src/tools/fetch/imls-pls.d.ts.map +1 -1
  308. package/out/src/tools/fetch/imls-pls.js +18 -18
  309. package/out/src/tools/fetch/imls-pls.js.map +1 -1
  310. package/out/src/tools/fetch/index.d.ts +3 -1
  311. package/out/src/tools/fetch/index.d.ts.map +1 -1
  312. package/out/src/tools/fetch/index.js +3 -1
  313. package/out/src/tools/fetch/index.js.map +1 -1
  314. package/out/src/tools/fetch/nad.d.ts +21 -7
  315. package/out/src/tools/fetch/nad.d.ts.map +1 -1
  316. package/out/src/tools/fetch/nad.js +5 -5
  317. package/out/src/tools/fetch/nad.js.map +1 -1
  318. package/out/src/tools/fetch/nppes.d.ts.map +1 -1
  319. package/out/src/tools/fetch/nppes.js +9 -15
  320. package/out/src/tools/fetch/nppes.js.map +1 -1
  321. package/out/src/tools/fetch/openaddresses.d.ts +3 -1
  322. package/out/src/tools/fetch/openaddresses.d.ts.map +1 -1
  323. package/out/src/tools/fetch/openaddresses.js +32 -23
  324. package/out/src/tools/fetch/openaddresses.js.map +1 -1
  325. package/out/src/tools/fetch/ppd.d.ts +3 -1
  326. package/out/src/tools/fetch/ppd.d.ts.map +1 -1
  327. package/out/src/tools/fetch/ppd.js +14 -3
  328. package/out/src/tools/fetch/ppd.js.map +1 -1
  329. package/out/src/tools/fetch/state-hi-schools.d.ts.map +1 -1
  330. package/out/src/tools/fetch/state-hi-schools.js +13 -6
  331. package/out/src/tools/fetch/state-hi-schools.js.map +1 -1
  332. package/out/src/tools/fetch/state-sources.d.ts.map +1 -1
  333. package/out/src/tools/fetch/state-sources.js +8 -3
  334. package/out/src/tools/fetch/state-sources.js.map +1 -1
  335. package/out/src/tools/fetch/tiger-full.d.ts +9 -3
  336. package/out/src/tools/fetch/tiger-full.d.ts.map +1 -1
  337. package/out/src/tools/fetch/tiger-full.js +35 -20
  338. package/out/src/tools/fetch/tiger-full.js.map +1 -1
  339. package/out/src/tools/gb-title-case.d.ts.map +1 -1
  340. package/out/src/tools/gb-title-case.js.map +1 -1
  341. package/out/src/tools/golden-expand.d.ts +24 -8
  342. package/out/src/tools/golden-expand.d.ts.map +1 -1
  343. package/out/src/tools/golden-expand.js +20 -12
  344. package/out/src/tools/golden-expand.js.map +1 -1
  345. package/out/src/tools/golden-promote.d.ts +18 -6
  346. package/out/src/tools/golden-promote.d.ts.map +1 -1
  347. package/out/src/tools/golden-promote.js +22 -7
  348. package/out/src/tools/golden-promote.js.map +1 -1
  349. package/out/src/tools/ingest-csv.d.ts +3 -1
  350. package/out/src/tools/ingest-csv.d.ts.map +1 -1
  351. package/out/src/tools/ingest-csv.js +17 -19
  352. package/out/src/tools/ingest-csv.js.map +1 -1
  353. package/out/src/tools/jsonl-to-parquet.d.ts +18 -6
  354. package/out/src/tools/jsonl-to-parquet.d.ts.map +1 -1
  355. package/out/src/tools/jsonl-to-parquet.js +11 -5
  356. package/out/src/tools/jsonl-to-parquet.js.map +1 -1
  357. package/out/src/tools/lint-shard-vocab.d.ts +36 -12
  358. package/out/src/tools/lint-shard-vocab.d.ts.map +1 -1
  359. package/out/src/tools/lint-shard-vocab.js +25 -11
  360. package/out/src/tools/lint-shard-vocab.js.map +1 -1
  361. package/out/src/tools/lint-shard.d.ts +30 -10
  362. package/out/src/tools/lint-shard.d.ts.map +1 -1
  363. package/out/src/tools/lint-shard.js +33 -20
  364. package/out/src/tools/lint-shard.js.map +1 -1
  365. package/out/src/tools/overlay-manifest.d.ts.map +1 -1
  366. package/out/src/tools/overlay-manifest.js +6 -4
  367. package/out/src/tools/overlay-manifest.js.map +1 -1
  368. package/out/src/tools/shard-kryptonite.d.ts +6 -2
  369. package/out/src/tools/shard-kryptonite.d.ts.map +1 -1
  370. package/out/src/tools/shard-kryptonite.js +1 -1
  371. package/out/src/tools/shard-kryptonite.js.map +1 -1
  372. package/out/src/tools/shard-translit.d.ts +9 -3
  373. package/out/src/tools/shard-translit.d.ts.map +1 -1
  374. package/out/src/tools/shard-translit.js +2 -2
  375. package/out/src/tools/shard-translit.js.map +1 -1
  376. package/out/src/types.d.ts +51 -17
  377. package/out/src/types.d.ts.map +1 -1
  378. package/out/src/wof-json.d.ts +9 -3
  379. package/out/src/wof-json.d.ts.map +1 -1
  380. package/out/src/wof-json.js +6 -4
  381. package/out/src/wof-json.js.map +1 -1
  382. package/package.json +7 -6
  383. package/src/adapter.ts +24 -13
  384. package/src/adapters/ban/adapter.ts +12 -2
  385. package/src/adapters/ban/street-decompose.ts +7 -1
  386. package/src/adapters/fcc-bdc/adapter.ts +19 -3
  387. package/src/adapters/geonames/adapter.ts +28 -5
  388. package/src/adapters/geonames-postal/adapter.ts +17 -1
  389. package/src/adapters/gnaf/adapter.ts +15 -2
  390. package/src/adapters/gnaf/assemble.ts +40 -10
  391. package/src/adapters/index.ts +13 -0
  392. package/src/adapters/openaddresses/adapter.ts +22 -3
  393. package/src/adapters/overture/adapter.ts +18 -2
  394. package/src/adapters/state-hi-schools/adapter.ts +15 -0
  395. package/src/adapters/state-ia-contractors/adapter.ts +15 -0
  396. package/src/adapters/state-ny-notaries/adapter.ts +15 -0
  397. package/src/adapters/state-tx-notaries/adapter.ts +18 -2
  398. package/src/adapters/synth-po-box/adapter.ts +19 -2
  399. package/src/adapters/tiger/adapter.ts +23 -4
  400. package/src/adapters/tiger/street-decompose.ts +1 -0
  401. package/src/adapters/usgov-hrsa-fqhc/adapter.ts +18 -2
  402. package/src/adapters/usgov-imls-pls/adapter.ts +15 -0
  403. package/src/adapters/usgov-irs-bmf/adapter.ts +19 -2
  404. package/src/adapters/usgov-nad/adapter.ts +14 -1
  405. package/src/adapters/usgov-nppes/adapter.ts +13 -0
  406. package/src/adapters/usgov-samhsa-treatment-locator/adapter.ts +21 -3
  407. package/src/adapters/wof-admin-jp/adapter.ts +20 -3
  408. package/src/adapters/wof-admin-json/adapter.ts +22 -7
  409. package/src/adapters/wof-postalcode-json/adapter.ts +10 -2
  410. package/src/align.ts +21 -8
  411. package/src/build.ts +48 -11
  412. package/src/codex/us-fips-state.ts +6 -2
  413. package/src/golden.ts +28 -13
  414. package/src/license.ts +4 -2
  415. package/src/parquet-wrapper/reader.ts +6 -4
  416. package/src/parquet-wrapper/schema.ts +14 -10
  417. package/src/parquet-wrapper/writer.ts +12 -4
  418. package/src/parquet.ts +39 -8
  419. package/src/runner.ts +49 -15
  420. package/src/shard-recipes/anchor-absorption.ts +21 -5
  421. package/src/shard-recipes/boundary-stress.ts +20 -7
  422. package/src/shard-recipes/country-balanced.ts +78 -13
  423. package/src/shard-recipes/cz-pcfirst-preposition.ts +9 -0
  424. package/src/shard-recipes/fr-admin-split.ts +30 -5
  425. package/src/shard-recipes/fr-bare-street.ts +10 -0
  426. package/src/shard-recipes/fr-fragment.ts +33 -8
  427. package/src/shard-recipes/fr-lieudit.ts +35 -9
  428. package/src/shard-recipes/fr-order.ts +47 -9
  429. package/src/shard-recipes/german.ts +32 -6
  430. package/src/shard-recipes/house-venue.ts +7 -0
  431. package/src/shard-recipes/index.ts +12 -4
  432. package/src/shard-recipes/intersection.ts +63 -14
  433. package/src/shard-recipes/locale.ts +37 -4
  434. package/src/shard-recipes/nl-postcode.ts +12 -2
  435. package/src/shard-recipes/no-fragment.ts +12 -2
  436. package/src/shard-recipes/no-street-led.ts +11 -1
  437. package/src/shard-recipes/no-street.ts +7 -0
  438. package/src/shard-recipes/po-box-cedex.ts +145 -45
  439. package/src/shard-recipes/po-box.ts +7 -0
  440. package/src/shard-recipes/scaffold.ts +52 -20
  441. package/src/shard-recipes/si-bare-village.ts +9 -0
  442. package/src/shard-recipes/street-affix.ts +88 -13
  443. package/src/shard-recipes/street-bare.ts +10 -0
  444. package/src/shard-recipes/street.ts +7 -0
  445. package/src/shard-recipes/unit.ts +79 -16
  446. package/src/split.ts +28 -7
  447. package/src/synthesize-anchor-absorption.ts +41 -14
  448. package/src/synthesize-boundary-stress.ts +57 -30
  449. package/src/synthesize-german.ts +30 -7
  450. package/src/synthesize-house-venue.ts +22 -16
  451. package/src/synthesize-intersection.ts +34 -7
  452. package/src/synthesize-no-street.ts +18 -10
  453. package/src/synthesize-po-box.ts +42 -10
  454. package/src/synthesize-street.ts +10 -2
  455. package/src/synthesize.ts +81 -38
  456. package/src/tokenize.ts +15 -5
  457. package/src/tools/align-shard.ts +6 -1
  458. package/src/tools/audit.ts +57 -11
  459. package/src/tools/corpus-stats.ts +9 -0
  460. package/src/tools/fetch/ban.ts +32 -10
  461. package/src/tools/fetch/download.ts +49 -12
  462. package/src/tools/fetch/hrsa.ts +3 -0
  463. package/src/tools/fetch/imls-pls.ts +28 -18
  464. package/src/tools/fetch/index.ts +3 -1
  465. package/src/tools/fetch/nad.ts +39 -12
  466. package/src/tools/fetch/nppes.ts +17 -15
  467. package/src/tools/fetch/openaddresses.ts +52 -24
  468. package/src/tools/fetch/ppd.ts +22 -3
  469. package/src/tools/fetch/state-hi-schools.ts +17 -6
  470. package/src/tools/fetch/state-sources.ts +16 -3
  471. package/src/tools/fetch/tiger-full.ts +66 -23
  472. package/src/tools/gb-title-case.ts +1 -0
  473. package/src/tools/golden-expand.ts +64 -20
  474. package/src/tools/golden-promote.ts +53 -13
  475. package/src/tools/ingest-csv.ts +41 -26
  476. package/src/tools/jsonl-to-parquet.ts +30 -10
  477. package/src/tools/lint-shard-vocab.ts +75 -24
  478. package/src/tools/lint-shard.ts +75 -31
  479. package/src/tools/overlay-manifest.ts +7 -4
  480. package/src/tools/shard-kryptonite.ts +11 -3
  481. package/src/tools/shard-translit.ts +20 -5
  482. package/src/types.ts +51 -17
  483. package/src/wof-json.ts +18 -7
@@ -39,14 +39,18 @@ import { join } from "node:path"
39
39
 
40
40
  import { dataRootPath } from "@mailwoman/core/utils"
41
41
 
42
- /** A column-projected base/shard row: parallel token + label lists plus the row's country. */
42
+ /**
43
+ * A column-projected base/shard row: parallel token + label lists plus the row's country.
44
+ */
43
45
  interface CorpusRow {
44
46
  tokens: string[]
45
47
  labels: string[]
46
48
  country: string | null
47
49
  }
48
50
 
49
- /** Strip a BIO prefix ("B-"/"I-") off a label, matching the Python `strip_bio`. */
51
+ /**
52
+ * Strip a BIO prefix ("B-"/"I-") off a label, matching the Python `strip_bio`.
53
+ */
50
54
  function stripBIO(label: string): string {
51
55
  const head = label.slice(0, 2)
52
56
 
@@ -77,7 +81,9 @@ function pyRound(x: number): number {
77
81
  return floor % 2 === 0 ? floor : floor + 1
78
82
  }
79
83
 
80
- /** Format a fraction as a whole-percent string the way Python's `:.0%` does, e.g. 0.73 -> "73%". */
84
+ /**
85
+ * Format a fraction as a whole-percent string the way Python's `:.0%` does, e.g. 0.73 -> "73%".
86
+ */
81
87
  function pct(frac: number): string {
82
88
  return `${pyRound(frac * 100)}%`
83
89
  }
@@ -91,7 +97,9 @@ function pyFloat(n: number): string {
91
97
  return Number.isInteger(n) ? n.toFixed(1) : String(n)
92
98
  }
93
99
 
94
- /** Left-justify to a minimum width with spaces, matching Python's `{value:N}` string field. */
100
+ /**
101
+ * Left-justify to a minimum width with spaces, matching Python's `{value:N}` string field.
102
+ */
95
103
  function pad(value: string, width: number): string {
96
104
  return value.padEnd(width)
97
105
  }
@@ -114,12 +122,14 @@ function dominant(counter: Map<string, number>): [string, number, number] {
114
122
  }
115
123
  }
116
124
 
117
- if (total === 0) return ["", 0, 0.0]
125
+ if (total === 0) return ["", 0, 0]
118
126
 
119
127
  return [bestTag, total, bestCount / total]
120
128
  }
121
129
 
122
- /** Bump a (key -> count) tally, creating the inner counter on first sight. */
130
+ /**
131
+ * Bump a (key -> count) tally, creating the inner counter on first sight.
132
+ */
123
133
  function bump(table: Map<string, Map<string, number>>, key: string, sub: string): void {
124
134
  let counter = table.get(key)
125
135
 
@@ -127,10 +137,13 @@ function bump(table: Map<string, Map<string, number>>, key: string, sub: string)
127
137
  counter = new Map()
128
138
  table.set(key, counter)
129
139
  }
140
+
130
141
  counter.set(sub, (counter.get(sub) ?? 0) + 1)
131
142
  }
132
143
 
133
- /** The DuckDB connection type, without a static dependency on the optional-peer package. */
144
+ /**
145
+ * The DuckDB connection type, without a static dependency on the optional-peer package.
146
+ */
134
147
  type DuckDBConnection = Awaited<
135
148
  ReturnType<Awaited<ReturnType<(typeof import("@duckdb/node-api"))["DuckDBInstance"]["create"]>>["connect"]>
136
149
  >
@@ -144,6 +157,7 @@ async function readRows(con: DuckDBConnection, path: string): Promise<CorpusRow[
144
157
  const result = await con.runAndReadAll(
145
158
  `SELECT to_json(tokens) AS tokens, to_json(labels) AS labels, country FROM read_parquet('${path}')`
146
159
  )
160
+
147
161
  const raw = result.getRowObjects() as Array<{ tokens: unknown; labels: unknown; country: unknown }>
148
162
  const rows: CorpusRow[] = []
149
163
 
@@ -152,6 +166,7 @@ async function readRows(con: DuckDBConnection, path: string): Promise<CorpusRow[
152
166
  const labels = JSON.parse(String(r.labels)) as unknown
153
167
 
154
168
  if (!Array.isArray(tokens) || !Array.isArray(labels)) continue
169
+
155
170
  rows.push({
156
171
  tokens: tokens as string[],
157
172
  labels: labels as string[],
@@ -162,7 +177,9 @@ async function readRows(con: DuckDBConnection, path: string): Promise<CorpusRow[
162
177
  return rows
163
178
  }
164
179
 
165
- /** Read just the first row's `source` value — used to group base parts for a proportional slice. */
180
+ /**
181
+ * Read just the first row's `source` value — used to group base parts for a proportional slice.
182
+ */
166
183
  async function readSource(con: DuckDBConnection, path: string): Promise<string> {
167
184
  const result = await con.runAndReadAll(`SELECT source FROM read_parquet('${path}') LIMIT 1`)
168
185
  const rows = result.getRowObjects() as Array<{ source: unknown }>
@@ -170,7 +187,9 @@ async function readSource(con: DuckDBConnection, path: string): Promise<string>
170
187
  return rows.length ? String(rows[0]!.source) : ""
171
188
  }
172
189
 
173
- /** Non-recursive `*.parquet` glob, sorted lexicographically — the Python `sorted(glob.glob(...))`. */
190
+ /**
191
+ * Non-recursive `*.parquet` glob, sorted lexicographically — the Python `sorted(glob.glob(...))`.
192
+ */
174
193
  function globParquet(dir: string): string[] {
175
194
  let names: string[]
176
195
 
@@ -183,44 +202,68 @@ function globParquet(dir: string): string[] {
183
202
  return names
184
203
  .filter((f) => f.endsWith(".parquet"))
185
204
  .map((f) => join(dir, f))
186
- .sort()
205
+ .toSorted()
187
206
  }
188
207
 
189
- /** Options for {@linkcode lintShardVocab}. */
208
+ /**
209
+ * Options for {@linkcode lintShardVocab}.
210
+ */
190
211
  export interface LintShardVocabOptions {
191
- /** The shard parquet to lint. */
212
+ /**
213
+ * The shard parquet to lint.
214
+ */
192
215
  shard: string
193
- /** Base corpus version. Default `v0.5.0`. */
216
+ /**
217
+ * Base corpus version. Default `v0.5.0`.
218
+ */
194
219
  baseVersion?: string
195
- /** Base corpus root. Default `$MAILWOMAN_DATA_ROOT/corpus/versioned`. */
220
+ /**
221
+ * Base corpus root. Default `$MAILWOMAN_DATA_ROOT/corpus/versioned`.
222
+ */
196
223
  baseRoot?: string
197
- /** Base-majority confidence floor for a contradiction. Default 0.7. */
224
+ /**
225
+ * Base-majority confidence floor for a contradiction. Default 0.7.
226
+ */
198
227
  threshold?: number
199
- /** Minimum base support to judge a token. Default 50. */
228
+ /**
229
+ * Minimum base support to judge a token. Default 50.
230
+ */
200
231
  minCount?: number
201
- /** Fraction of base parts to scan (proportional per-source slice below 1.0). Default 1.0. */
232
+ /**
233
+ * Fraction of base parts to scan (proportional per-source slice below 1.0). Default 1.0.
234
+ */
202
235
  fraction?: number
203
236
  }
204
237
 
205
- /** One contradiction row: token, shard tag, base tag, base fraction, base total. */
238
+ /**
239
+ * One contradiction row: token, shard tag, base tag, base fraction, base total.
240
+ */
206
241
  export type ShardVocabRow = [token: string, shardTag: string, baseTag: string, baseFrac: number, baseTotal: number]
207
242
 
208
- /** Findings summary returned by {@linkcode lintShardVocab}. */
243
+ /**
244
+ * Findings summary returned by {@linkcode lintShardVocab}.
245
+ */
209
246
  export interface LintShardVocabSummary {
210
- /** Real contradictions — the command exits 1 when nonzero. */
247
+ /**
248
+ * Real contradictions — the command exits 1 when nonzero.
249
+ */
211
250
  errors: number
212
- /** Affix-split rows (EXPECTED — the loader's affix-relabel handles them). */
251
+ /**
252
+ * Affix-split rows (EXPECTED — the loader's affix-relabel handles them).
253
+ */
213
254
  warnings: number
214
255
  findings: { contradictions: ShardVocabRow[]; affixSplits: ShardVocabRow[] }
215
256
  }
216
257
 
217
- /** Lint a synthetic shard's (token → tag) vocabulary against the base corpus, country-scoped. */
258
+ /**
259
+ * Lint a synthetic shard's (token → tag) vocabulary against the base corpus, country-scoped.
260
+ */
218
261
  export async function lintShardVocab(options: LintShardVocabOptions): Promise<LintShardVocabSummary> {
219
262
  const baseVersion = options.baseVersion ?? "v0.5.0"
220
263
  const baseRoot = options.baseRoot ?? dataRootPath("corpus", "versioned")
221
264
  const threshold = options.threshold ?? 0.7
222
265
  const minCount = options.minCount ?? 50
223
- const fraction = options.fraction ?? 1.0
266
+ const fraction = options.fraction ?? 1
224
267
 
225
268
  // @duckdb/node-api is an optional peer — lazy import (the pipeline convention).
226
269
  const { DuckDBInstance } = await import("@duckdb/node-api")
@@ -247,10 +290,13 @@ export async function lintShardVocab(options: LintShardVocabOptions): Promise<Li
247
290
  set = new Set()
248
291
  shardCountries.set(w, set)
249
292
  }
293
+
250
294
  set.add(country)
251
295
  }
252
296
  }
297
+
253
298
  const shardVocab = new Set(shardTags.keys())
299
+
254
300
  console.log(`shard: ${shardRows.length} rows, ${shardVocab.size} unique tokens`)
255
301
 
256
302
  // 2. base parts — FULL by default; fraction<1 takes a proportional per-source slice (still big)
@@ -261,7 +307,7 @@ export async function lintShardVocab(options: LintShardVocabOptions): Promise<Li
261
307
  throw new Error("no base parts found")
262
308
  }
263
309
 
264
- if (fraction < 1.0) {
310
+ if (fraction < 1) {
265
311
  const bysrc = new Map<string, string[]>()
266
312
 
267
313
  for (const p of parts) {
@@ -272,8 +318,10 @@ export async function lintShardVocab(options: LintShardVocabOptions): Promise<Li
272
318
  list = []
273
319
  bysrc.set(src, list)
274
320
  }
321
+
275
322
  list.push(p)
276
323
  }
324
+
277
325
  const sliced: string[] = []
278
326
 
279
327
  for (const ps of bysrc.values()) {
@@ -283,8 +331,10 @@ export async function lintShardVocab(options: LintShardVocabOptions): Promise<Li
283
331
  sliced.push(p)
284
332
  }
285
333
  }
334
+
286
335
  parts = sliced
287
336
  }
337
+
288
338
  console.log(`base ${baseVersion}: scanning ${parts.length} parts (fraction=${pyFloat(fraction)}), COUNTRY-scoped`)
289
339
 
290
340
  // 3. tally each shard token's base tag, SCOPED to the country the shard uses it in
@@ -336,6 +386,7 @@ export async function lintShardVocab(options: LintShardVocabOptions): Promise<Li
336
386
  for (const [label, rows] of sections) {
337
387
  if (!rows.length) continue
338
388
  rows.sort((a, b) => b[4] - a[4] || b[3] - a[3])
389
+
339
390
  console.log(`\n${label.startsWith("CONTRA") ? "⚠️ " : "· "}${rows.length} ${label}:`)
340
391
 
341
392
  for (const [w, sTag, bTag, bFrac, bTotal] of rows) {
@@ -39,10 +39,22 @@ import { execSync } from "node:child_process"
39
39
  import { existsSync, readFileSync, writeFileSync } from "node:fs"
40
40
  import { fileURLToPath } from "node:url"
41
41
 
42
+ /**
43
+ * Occurrences of a forbidden label before it is reported — one or two are noise, five is a pattern.
44
+ */
45
+ const FORBIDDEN_LABEL_REPORT_THRESHOLD = 5
46
+
47
+ /**
48
+ * Examples printed per finding before the list is truncated.
49
+ */
50
+ const MAX_LISTED_EXAMPLES = 20
51
+
42
52
  const SEP = ""
43
53
 
44
- // Calibrated thresholds (DeepSeek turn 9). These can be tuned over time if new failure
45
- // modes surface that the current numbers miss.
54
+ /**
55
+ * Calibrated thresholds (DeepSeek turn 9). These can be tuned over time if new failure modes surface that the current
56
+ * numbers miss.
57
+ */
46
58
  const CORPUS_CONFIDENCE_FLOOR = 0.66
47
59
  const SHARD_MIN_COUNT = 50
48
60
  const CORPUS_MIN_COUNT = 200
@@ -65,17 +77,29 @@ function defaultRulesPath(): string {
65
77
  return fileURLToPath(new URL("../../../src/tools/lint-rules.json", import.meta.url))
66
78
  }
67
79
 
68
- /** Options for {@linkcode lintCorpusShard}. */
80
+ /**
81
+ * Options for {@linkcode lintCorpusShard}.
82
+ */
69
83
  export interface LintCorpusShardOptions {
70
- /** The new shard parquet to lint. */
84
+ /**
85
+ * The new shard parquet to lint.
86
+ */
71
87
  shardPath: string
72
- /** Pre-computed corpus stats JSON (see `corpus-stats.ts`). */
88
+ /**
89
+ * Pre-computed corpus stats JSON (see `corpus-stats.ts`).
90
+ */
73
91
  statsPath: string
74
- /** Anti-pattern rules JSON. Default: the `lint-rules.json` beside this module. */
92
+ /**
93
+ * Anti-pattern rules JSON. Default: the `lint-rules.json` beside this module.
94
+ */
75
95
  rulesPath?: string
76
- /** Write the markdown report here as well as stdout. */
96
+ /**
97
+ * Write the markdown report here as well as stdout.
98
+ */
77
99
  outMd?: string
78
- /** Write a JSON sidecar of the flags + summary here. */
100
+ /**
101
+ * Write a JSON sidecar of the flags + summary here.
102
+ */
79
103
  outJson?: string
80
104
  }
81
105
 
@@ -114,6 +138,7 @@ labels_col = t['labels'].to_pylist()
114
138
  for i in range(len(tokens_col)):
115
139
  sys.stdout.write(json.dumps({"tokens": tokens_col[i], "labels": labels_col[i]}) + "\\n")
116
140
  `
141
+
117
142
  const buf = execSync(`python3`, { input: py, maxBuffer: 1024 * 1024 * 1024 })
118
143
  const rows: ShardRow[] = []
119
144
 
@@ -145,6 +170,7 @@ function statsFromShard(rows: ShardRow[]): ShardStats {
145
170
  for (const row of rows) {
146
171
  if (row.tokens.length !== row.labels.length) {
147
172
  out.truncatedRows++
173
+
148
174
  continue
149
175
  }
150
176
 
@@ -161,6 +187,7 @@ function statsFromShard(rows: ShardRow[]): ShardStats {
161
187
  labelMap = new Map()
162
188
  out.tokens.set(tk, labelMap)
163
189
  }
190
+
164
191
  labelMap.set(lb, (labelMap.get(lb) ?? 0) + 1)
165
192
 
166
193
  if (i + 1 < row.tokens.length) {
@@ -172,6 +199,7 @@ function statsFromShard(rows: ShardRow[]): ShardStats {
172
199
  bMap = new Map()
173
200
  out.bigrams.set(bigramKey, bMap)
174
201
  }
202
+
175
203
  bMap.set(bigramLabel, (bMap.get(bigramLabel) ?? 0) + 1)
176
204
  }
177
205
  }
@@ -203,7 +231,9 @@ function majorityLabel(distribution: Map<string, number> | Record<string, number
203
231
  return { label: bestLabel, count: bestCount, total, confidence: total === 0 ? 0 : bestCount / total }
204
232
  }
205
233
 
206
- /** One lint flag emitted by a check. */
234
+ /**
235
+ * One lint flag emitted by a check.
236
+ */
207
237
  export interface LintShardFlag {
208
238
  check: string
209
239
  severity: "error" | "warn"
@@ -217,12 +247,16 @@ export interface LintShardFlag {
217
247
  ruleID?: string
218
248
  }
219
249
 
220
- /** Findings summary returned by {@linkcode lintCorpusShard}. */
250
+ /**
251
+ * Findings summary returned by {@linkcode lintCorpusShard}.
252
+ */
221
253
  export interface LintCorpusShardSummary {
222
254
  errors: number
223
255
  warnings: number
224
256
  findings: LintShardFlag[]
225
- /** The rendered markdown report (also printed to stdout). */
257
+ /**
258
+ * The rendered markdown report (also printed to stdout).
259
+ */
226
260
  report: string
227
261
  }
228
262
 
@@ -307,6 +341,7 @@ function checkBigramCollisions(shard: ShardStats, corpus: CorpusStats): LintShar
307
341
  const renderBigram = bigram.split(SEP).join(" ")
308
342
  const renderShardLabel = shardMaj.label.split(SEP).join(" → ")
309
343
  const renderCorpusLabel = corpusMaj.label.split(SEP).join(" → ")
344
+
310
345
  flags.push({
311
346
  check: "bigram-collision",
312
347
  severity: "error",
@@ -325,6 +360,7 @@ function checkBigramCollisions(shard: ShardStats, corpus: CorpusStats): LintShar
325
360
 
326
361
  function checkRules(shard: ShardStats, rulesFile: LintRulesFile): LintShardFlag[] {
327
362
  const flags: LintShardFlag[] = []
363
+
328
364
  const compiled = rulesFile.rules.map((r) => ({
329
365
  rule: r,
330
366
  regex: new RegExp(r.pattern, r.pattern_case_sensitive ? "" : "i"),
@@ -335,7 +371,7 @@ function checkRules(shard: ShardStats, rulesFile: LintRulesFile): LintShardFlag[
335
371
  if (!regex.test(token)) continue
336
372
 
337
373
  for (const [label, count] of labelMap) {
338
- if (rule.forbidden_labels.includes(label) && count >= 5) {
374
+ if (rule.forbidden_labels.includes(label) && count >= FORBIDDEN_LABEL_REPORT_THRESHOLD) {
339
375
  flags.push({
340
376
  check: "anti-pattern-rule",
341
377
  severity: rule.severity,
@@ -363,6 +399,7 @@ function checkSanity(shard: ShardStats): LintShardFlag[] {
363
399
  detail: `${shard.truncatedRows} row(s) have tokens.length !== labels.length. Pipeline alignment bug.`,
364
400
  })
365
401
  }
402
+
366
403
  const allORatio = shard.allORows / Math.max(1, shard.rowCount)
367
404
 
368
405
  if (allORatio >= ALL_O_RATIO_CEILING) {
@@ -383,28 +420,29 @@ function renderReport(
383
420
  ): string {
384
421
  const errors = flags.filter((f) => f.severity === "error")
385
422
  const warns = flags.filter((f) => f.severity === "warn")
386
- const verdict = errors.length === 0 ? "**PASS** ✓" : "**FLAGGED** ⚠"
387
- const lines: string[] = []
388
- lines.push(`# Corpus Lint: ${verdict}`)
389
- lines.push("")
390
- lines.push(`- **Shard:** \`${opts.shardPath}\``)
391
- lines.push(`- **Corpus stats:** \`${opts.statsPath}\``)
392
- lines.push(`- **Rules:** \`${opts.rulesPath}\``)
393
- lines.push(`- **Shard rows:** ${shard.rowCount}`)
394
- lines.push(`- **Unique tokens:** ${shard.tokens.size}`)
395
- lines.push(`- **Unique bigrams:** ${shard.bigrams.size}`)
396
- lines.push("")
397
- lines.push(
398
- `**Errors:** ${errors.length} (gates the shard's inclusion unless MANIFEST sets \`lint_acknowledged: true\`)`
399
- )
400
- lines.push(`**Warnings:** ${warns.length} (advisory)`)
401
- lines.push("")
423
+ const verdict = !errors.length ? "**PASS** ✓" : "**FLAGGED** ⚠"
424
+
425
+ const lines: string[] = [
426
+ `# Corpus Lint: ${verdict}`,
427
+ "",
428
+ `- **Shard:** \`${opts.shardPath}\``,
429
+ `- **Corpus stats:** \`${opts.statsPath}\``,
430
+ `- **Rules:** \`${opts.rulesPath}\``,
431
+ `- **Shard rows:** ${shard.rowCount}`,
432
+ `- **Unique tokens:** ${shard.tokens.size}`,
433
+ `- **Unique bigrams:** ${shard.bigrams.size}`,
434
+ "",
435
+ `**Errors:** ${errors.length} (gates the shard's inclusion unless MANIFEST sets \`lint_acknowledged: true\`)`,
436
+ `**Warnings:** ${warns.length} (advisory)`,
437
+ "",
438
+ ]
402
439
 
403
- if (flags.length === 0) {
440
+ if (!flags.length) {
404
441
  lines.push("No anomalies detected.")
405
442
 
406
443
  return lines.join("\n")
407
444
  }
445
+
408
446
  const byCheck = new Map<string, LintShardFlag[]>()
409
447
 
410
448
  for (const f of flags) {
@@ -423,16 +461,19 @@ function renderReport(
423
461
  lines.push(`- **[${f.severity.toUpperCase()}]** ${f.detail}`)
424
462
  }
425
463
 
426
- if (list.length > 20) {
464
+ if (list.length > MAX_LISTED_EXAMPLES) {
427
465
  lines.push(`- ... and ${list.length - 20} more`)
428
466
  }
467
+
429
468
  lines.push("")
430
469
  }
431
470
 
432
471
  return lines.join("\n")
433
472
  }
434
473
 
435
- /** Lint a shard against corpus stats + the anti-pattern rules; print the markdown report to stdout. */
474
+ /**
475
+ * Lint a shard against corpus stats + the anti-pattern rules; print the markdown report to stdout.
476
+ */
436
477
  export function lintCorpusShard(
437
478
  options: LintCorpusShardOptions,
438
479
  report?: (line: string) => void
@@ -440,6 +481,7 @@ export function lintCorpusShard(
440
481
  const rulesPath = options.rulesPath ?? defaultRulesPath()
441
482
  report?.(`Reading corpus stats from ${options.statsPath}...`)
442
483
  const corpus: CorpusStats = JSON.parse(readFileSync(options.statsPath, "utf8"))
484
+
443
485
  report?.(
444
486
  ` ${corpus.row_count} rows from ${corpus.shard_paths.length} shard(s); ${Object.keys(corpus.tokens).length} tokens, ${Object.keys(corpus.bigrams).length} bigrams`
445
487
  )
@@ -455,6 +497,7 @@ export function lintCorpusShard(
455
497
  const rulesFile: LintRulesFile = JSON.parse(readFileSync(rulesPath, "utf8"))
456
498
 
457
499
  report?.(`Running checks...`)
500
+
458
501
  const flags: LintShardFlag[] = [
459
502
  ...checkDistributionOutliers(shard, corpus),
460
503
  ...checkLabelVacuum(shard, corpus),
@@ -464,6 +507,7 @@ export function lintCorpusShard(
464
507
  ]
465
508
 
466
509
  const rendered = renderReport({ shardPath: options.shardPath, statsPath: options.statsPath, rulesPath }, shard, flags)
510
+
467
511
  console.log(rendered)
468
512
 
469
513
  if (options.outMd) {
@@ -51,9 +51,11 @@ interface BaseManifest {
51
51
  total_rows: number
52
52
  }
53
53
 
54
- /** Escape a path for single-quoted SQL string literals. */
54
+ /**
55
+ * Escape a path for single-quoted SQL string literals.
56
+ */
55
57
  function sqlString(value: string): string {
56
- return value.replace(/'/g, "''")
58
+ return value.replaceAll("'", "''")
57
59
  }
58
60
 
59
61
  async function descriptor(
@@ -78,7 +80,7 @@ async function descriptor(
78
80
  bytes: statSync(localPath).size,
79
81
  sha256: sha256Hex(readFileSync(localPath)),
80
82
  first_source_id: sids[0]!,
81
- last_source_id: sids[sids.length - 1]!,
83
+ last_source_id: sids.at(-1)!,
82
84
  source,
83
85
  }
84
86
  }
@@ -103,7 +105,7 @@ export async function assembleOverlayManifest(args: OverlayManifestOptions): Pro
103
105
  const reroot = (p: string): string => {
104
106
  const i = p.indexOf("/corpus/versioned/")
105
107
 
106
- return i >= 0 ? "/data" + p.slice(i) : p
108
+ return i !== -1 ? "/data" + p.slice(i) : p
107
109
  }
108
110
 
109
111
  const kept = base.shards.map((s) => ({ ...s, path: reroot(s.path) }))
@@ -134,6 +136,7 @@ export async function assembleOverlayManifest(args: OverlayManifestOptions): Pro
134
136
 
135
137
  const out = join(args.newDir, "MANIFEST.json")
136
138
  writeFileSync(out, JSON.stringify(manifest, null, 1) + "\n")
139
+
137
140
  console.log(`wrote ${out}`)
138
141
  console.log(` shards: ${manifest.shards.length} (${kept.length} base kept, +1 ${args.source})`)
139
142
  console.log(` counts: ${JSON.stringify(manifest.counts)} total: ${manifest.total_rows}`)
@@ -31,9 +31,13 @@ export interface ShardKryptoniteOptions {
31
31
  jsonl: string
32
32
  baseManifest: string
33
33
  outDir: string
34
- /** Default `"0.4.0"`. */
34
+ /**
35
+ * Default `"0.4.0"`.
36
+ */
35
37
  corpusVersion?: string
36
- /** Default `"deepseek-kryptonite"`. */
38
+ /**
39
+ * Default `"deepseek-kryptonite"`.
40
+ */
37
41
  source?: string
38
42
  }
39
43
 
@@ -41,6 +45,7 @@ async function* canonicalRows(jsonl: string, corpusVersion: string): AsyncIterab
41
45
  for await (const raw of iterateJSONL<Record<string, unknown>>(jsonl)) {
42
46
  // Strip sidecar underscore-prefixed fields the generator left behind for debugging.
43
47
  const components = raw["components"] as Record<string, string>
48
+
44
49
  yield {
45
50
  raw: raw["raw"] as string,
46
51
  components,
@@ -81,6 +86,7 @@ export async function buildKryptoniteShard(
81
86
  await mkdir(options.outDir, { recursive: true })
82
87
 
83
88
  const quarantine: string[] = []
89
+
84
90
  const newManifest = await writeShards(
85
91
  { train: labeledRows(options.jsonl, corpusVersion, quarantine) },
86
92
  { outputDir: options.outDir, corpusVersion }
@@ -91,7 +97,7 @@ export async function buildKryptoniteShard(
91
97
  `quarantined ${quarantine.length}`
92
98
  )
93
99
 
94
- if (quarantine.length > 0) {
100
+ if (quarantine.length) {
95
101
  const qPath = join(options.outDir, `corpus-v${corpusVersion}`, "quarantine-kryptonite.tsv")
96
102
  writeFileSync(qPath, quarantine.join("\n") + "\n", "utf8")
97
103
  report?.(`quarantine log → ${qPath}`)
@@ -106,6 +112,7 @@ export async function buildKryptoniteShard(
106
112
 
107
113
  // Compose the final corpus-v0.4.0 manifest: every shard from base + the new shard(s).
108
114
  const base = JSON.parse(readFileSync(options.baseManifest, "utf8")) as ShardManifest
115
+
109
116
  const combined: ShardManifest = {
110
117
  corpus_version: corpusVersion,
111
118
  schema: PARQUET_COLUMNS,
@@ -119,6 +126,7 @@ export async function buildKryptoniteShard(
119
126
  },
120
127
  total_rows: base.total_rows + newManifest.total_rows,
121
128
  }
129
+
122
130
  // Stamp source on the legacy v0.3.0 shards too, so audit's shard.source path is the
123
131
  // authoritative one. v0.3.0 shards mix sources; we use the first_source_id-prefix
124
132
  // inference for them (audit.ts will re-derive on its own when shard.source is absent).
@@ -44,11 +44,17 @@ export interface ShardTranslitOptions {
44
44
  jsonl: string
45
45
  baseManifest: string
46
46
  outDir: string
47
- /** Default `"0.4.0"`. */
47
+ /**
48
+ * Default `"0.4.0"`.
49
+ */
48
50
  corpusVersion?: string
49
- /** Default `"/data/"`. */
51
+ /**
52
+ * Default `"/data/"`.
53
+ */
50
54
  canonicalPathPrefix?: string
51
- /** Default `"/mnt/playpen/mailwoman-data/"`. */
55
+ /**
56
+ * Default `"/mnt/playpen/mailwoman-data/"`.
57
+ */
52
58
  legacyPathPrefix?: string
53
59
  }
54
60
 
@@ -106,6 +112,7 @@ async function writeOneShard(
106
112
  const writer = await ParquetWriter.openFile<ParquetRow>(LABELED_ROW_SCHEMA, outPath, {
107
113
  rowGroupSize: ROW_GROUP_SIZE,
108
114
  })
115
+
109
116
  writer.setMetadata("mailwoman.corpus_version", corpusVersion)
110
117
  writer.setMetadata("mailwoman.split", "train")
111
118
  writer.setMetadata("mailwoman.shard_source", source)
@@ -120,8 +127,10 @@ async function writeOneShard(
120
127
  if (firstSourceID === "") {
121
128
  firstSourceID = row.source_id
122
129
  }
130
+
123
131
  lastSourceID = row.source_id
124
132
  }
133
+
125
134
  await writer.close()
126
135
 
127
136
  const fileStat = await stat(outPath)
@@ -177,8 +186,10 @@ export async function buildTranslitShard(
177
186
 
178
187
  if (result.kind !== "labeled") {
179
188
  quarantine.push(`${canon.source_id}\t${result.row.reason}`)
189
+
180
190
  continue
181
191
  }
192
+
182
193
  const bucket = buckets.get(canon.source)
183
194
 
184
195
  if (bucket) {
@@ -187,10 +198,11 @@ export async function buildTranslitShard(
187
198
  buckets.set(canon.source, [result.row])
188
199
  }
189
200
  }
201
+
190
202
  report?.(`read ${totalIn} rows; ${quarantine.length} quarantined; ${buckets.size} script buckets`)
191
203
 
192
204
  const newShards: ShardDescriptor[] = []
193
- const sortedKeys = [...buckets.keys()].sort()
205
+ const sortedKeys = [...buckets.keys()].toSorted()
194
206
 
195
207
  for (const source of sortedKeys) {
196
208
  const rows = buckets.get(source)!
@@ -201,7 +213,7 @@ export async function buildTranslitShard(
201
213
  report?.(` ${source}: ${descriptor.rows} rows → ${outPath} (${descriptor.bytes} bytes)`)
202
214
  }
203
215
 
204
- if (quarantine.length > 0) {
216
+ if (quarantine.length) {
205
217
  const qPath = join(corpusDir, "quarantine-transliteration.tsv")
206
218
  writeFileSync(qPath, quarantine.join("\n") + "\n", "utf8")
207
219
  report?.(`quarantine log → ${qPath} (${quarantine.length} rows)`)
@@ -211,11 +223,14 @@ export async function buildTranslitShard(
211
223
  // the new translit shards. Kryptonite shard already lives in the base manifest (it was written
212
224
  // there by Thread B).
213
225
  const base = JSON.parse(readFileSync(options.baseManifest, "utf8")) as ShardManifest
226
+
214
227
  const rewrittenBase = base.shards.map((sh) => ({
215
228
  ...sh,
216
229
  path: canonicalizeShardPath(sh.path, legacyPathPrefix, canonicalPathPrefix),
217
230
  }))
231
+
218
232
  const newTrainRows = newShards.reduce((sum, sh) => sum + sh.rows, 0)
233
+
219
234
  const combined: ShardManifest = {
220
235
  corpus_version: corpusVersion,
221
236
  schema: PARQUET_COLUMNS,