@mailwoman/resolver-wof-sqlite 9.2.0 → 9.4.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 (493) hide show
  1. package/README.md +16 -19
  2. package/lib/address/index.ts +9 -0
  3. package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +25 -24
  4. package/{address-point-schema.ts → lib/address/point-schema.ts} +18 -4
  5. package/lib/address/point.ts +328 -0
  6. package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
  7. package/{ancestry.ts → lib/ancestry/index.ts} +5 -4
  8. package/{build-candidate.ts → lib/build-candidate.ts} +99 -79
  9. package/{build-slim.ts → lib/build-slim.ts} +150 -165
  10. package/{candidate → lib/candidate}/alias-bags.ts +8 -6
  11. package/{candidate → lib/candidate}/ancestors-sidecar.ts +13 -15
  12. package/{candidate → lib/candidate}/country-display-names.ts +2 -2
  13. package/lib/candidate/extract-fold.ts +219 -0
  14. package/{candidate → lib/candidate}/name-roles.ts +17 -16
  15. package/{candidate → lib/candidate}/own-name.ts +2 -1
  16. package/{candidate → lib/candidate}/place-attrs.ts +3 -3
  17. package/{candidate-ancestors-schema.ts → lib/candidate-ancestors-schema.ts} +4 -4
  18. package/{candidate-fts.ts → lib/candidate-fts.ts} +3 -3
  19. package/{candidate-importance.ts → lib/candidate-importance.ts} +53 -57
  20. package/{candidate-lookup.ts → lib/candidate-lookup.ts} +84 -80
  21. package/{candidate-schema.ts → lib/candidate-schema.ts} +6 -6
  22. package/{candidate-scoring.ts → lib/candidate-scoring.ts} +15 -22
  23. package/{capital-schema.ts → lib/capital-schema.ts} +5 -6
  24. package/{capitals.ts → lib/capitals.ts} +2 -2
  25. package/{coincident-roles.ts → lib/coincident-roles.ts} +9 -13
  26. package/{convention.ts → lib/convention/index.ts} +3 -3
  27. package/{convention-schema.ts → lib/convention/schema.ts} +2 -2
  28. package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +10 -10
  29. package/{currency-backfill.ts → lib/currency-backfill.ts} +126 -41
  30. package/lib/env.ts +50 -0
  31. package/{exact-match.ts → lib/exact-match.ts} +23 -14
  32. package/{sharding.ts → lib/extracts.ts} +61 -58
  33. package/{fst-autocomplete.ts → lib/fst/autocomplete.ts} +4 -4
  34. package/{fst-builder.ts → lib/fst/builder.ts} +17 -16
  35. package/{fst-deserialize-web.ts → lib/fst/deserialize-web.ts} +27 -87
  36. package/lib/fst/format.ts +106 -0
  37. package/{fst-freshness.ts → lib/fst/freshness.ts} +40 -74
  38. package/lib/fst/index.ts +14 -0
  39. package/{fst-matcher.ts → lib/fst/matcher.ts} +1 -1
  40. package/{fst-serialize.ts → lib/fst/serialize.ts} +37 -115
  41. package/{fst-types.ts → lib/fst/types.ts} +4 -2
  42. package/{fts.ts → lib/fts/index.ts} +24 -19
  43. package/{fts-query.ts → lib/fts/query.ts} +1 -1
  44. package/{geonames-aliases.ts → lib/geonames/aliases.ts} +13 -13
  45. package/lib/geonames/index.ts +8 -0
  46. package/{geonames-postal.ts → lib/geonames/postal.ts} +14 -13
  47. package/{index.ts → lib/index.ts} +37 -37
  48. package/{interpolation.ts → lib/interpolation.ts} +28 -26
  49. package/{lookup.ts → lib/lookup.ts} +130 -142
  50. package/lib/nsul/index.ts +8 -0
  51. package/lib/nsul/lookup.ts +144 -0
  52. package/lib/nsul/schema.ts +130 -0
  53. package/{place-importance-schema.ts → lib/place-importance-schema.ts} +7 -16
  54. package/lib/poi/index.ts +8 -0
  55. package/{poi-lookup.ts → lib/poi/lookup.ts} +22 -29
  56. package/{poi-schema.ts → lib/poi/schema.ts} +3 -4
  57. package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +14 -20
  58. package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +2 -2
  59. package/lib/postal/index.ts +9 -0
  60. package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
  61. package/{primary-preference.ts → lib/primary-preference.ts} +43 -14
  62. package/{proximity-rerank.ts → lib/proximity-rerank.ts} +2 -2
  63. package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
  64. package/{region-keys.ts → lib/region-keys.ts} +9 -9
  65. package/{reverse.ts → lib/reverse.ts} +34 -47
  66. package/{schema.ts → lib/schema.ts} +10 -0
  67. package/{search-fetch.ts → lib/search-fetch.ts} +29 -29
  68. package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
  69. package/{sqlite-utils.ts → lib/sqlite-utils.ts} +14 -19
  70. package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +5 -5
  71. package/{street-centroid.ts → lib/street/centroid.ts} +15 -22
  72. package/lib/street/index.ts +13 -0
  73. package/{street-morphology-fst-builder.ts → lib/street/morphology-fst-builder.ts} +24 -14
  74. package/{street-morphology-fst-loader.ts → lib/street/morphology-fst-loader.ts} +14 -12
  75. package/{street-name-lookup.ts → lib/street/name-lookup.ts} +14 -30
  76. package/{street-normalize.ts → lib/street/normalize.ts} +86 -20
  77. package/{street-segment-schema.ts → lib/street/segment-schema.ts} +7 -7
  78. package/{types.ts → lib/types.ts} +18 -12
  79. package/{unified-schema.ts → lib/unified-schema.ts} +20 -24
  80. package/lib/uprn/existence.ts +84 -0
  81. package/lib/uprn/index.ts +9 -0
  82. package/{uprn-lookup.ts → lib/uprn/lookup.ts} +14 -19
  83. package/{uprn-schema.ts → lib/uprn/schema.ts} +3 -3
  84. package/lib/weights-overlay-linker.ts +879 -0
  85. package/out/address/index.d.ts +9 -0
  86. package/out/address/index.d.ts.map +1 -0
  87. package/out/address/index.js +9 -0
  88. package/out/address/index.js.map +1 -0
  89. package/out/{address-point-interpolation.d.ts → address/point-interpolation.d.ts} +12 -11
  90. package/out/address/point-interpolation.d.ts.map +1 -0
  91. package/out/{address-point-interpolation.js → address/point-interpolation.js} +18 -18
  92. package/out/address/point-interpolation.js.map +1 -0
  93. package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +16 -6
  94. package/out/address/point-schema.d.ts.map +1 -0
  95. package/out/{address-point-schema.js → address/point-schema.js} +7 -3
  96. package/out/address/point-schema.js.map +1 -0
  97. package/out/{address-point.d.ts → address/point.d.ts} +19 -9
  98. package/out/address/point.d.ts.map +1 -0
  99. package/out/address/point.js +222 -0
  100. package/out/address/point.js.map +1 -0
  101. package/out/{ancestry-backfill.d.ts → ancestry/backfill.d.ts} +7 -5
  102. package/out/ancestry/backfill.d.ts.map +1 -0
  103. package/out/{ancestry-backfill.js → ancestry/backfill.js} +12 -16
  104. package/out/ancestry/backfill.js.map +1 -0
  105. package/out/{ancestry.d.ts → ancestry/index.d.ts} +4 -3
  106. package/out/ancestry/index.d.ts.map +1 -0
  107. package/out/{ancestry.js → ancestry/index.js} +3 -2
  108. package/out/ancestry/index.js.map +1 -0
  109. package/out/build-candidate.d.ts +32 -24
  110. package/out/build-candidate.d.ts.map +1 -1
  111. package/out/build-candidate.js +60 -54
  112. package/out/build-candidate.js.map +1 -1
  113. package/out/build-slim.d.ts +4 -4
  114. package/out/build-slim.d.ts.map +1 -1
  115. package/out/build-slim.js +124 -139
  116. package/out/build-slim.js.map +1 -1
  117. package/out/candidate/alias-bags.d.ts +5 -3
  118. package/out/candidate/alias-bags.d.ts.map +1 -1
  119. package/out/candidate/alias-bags.js +2 -2
  120. package/out/candidate/alias-bags.js.map +1 -1
  121. package/out/candidate/ancestors-sidecar.d.ts +9 -10
  122. package/out/candidate/ancestors-sidecar.d.ts.map +1 -1
  123. package/out/candidate/ancestors-sidecar.js +7 -7
  124. package/out/candidate/ancestors-sidecar.js.map +1 -1
  125. package/out/candidate/country-display-names.d.ts +1 -1
  126. package/out/candidate/country-display-names.d.ts.map +1 -1
  127. package/out/candidate/country-display-names.js +1 -1
  128. package/out/candidate/country-display-names.js.map +1 -1
  129. package/out/candidate/extract-fold.d.ts +41 -0
  130. package/out/candidate/extract-fold.d.ts.map +1 -0
  131. package/out/candidate/extract-fold.js +153 -0
  132. package/out/candidate/extract-fold.js.map +1 -0
  133. package/out/candidate/name-roles.d.ts +13 -11
  134. package/out/candidate/name-roles.d.ts.map +1 -1
  135. package/out/candidate/name-roles.js +11 -10
  136. package/out/candidate/name-roles.js.map +1 -1
  137. package/out/candidate/own-name.d.ts +1 -1
  138. package/out/candidate/own-name.d.ts.map +1 -1
  139. package/out/candidate/own-name.js +2 -1
  140. package/out/candidate/own-name.js.map +1 -1
  141. package/out/candidate/place-attrs.d.ts +3 -3
  142. package/out/candidate/place-attrs.d.ts.map +1 -1
  143. package/out/candidate/place-attrs.js +1 -1
  144. package/out/candidate/place-attrs.js.map +1 -1
  145. package/out/candidate-ancestors-schema.d.ts +4 -4
  146. package/out/candidate-ancestors-schema.d.ts.map +1 -1
  147. package/out/candidate-ancestors-schema.js +2 -2
  148. package/out/candidate-ancestors-schema.js.map +1 -1
  149. package/out/candidate-fts.d.ts +3 -3
  150. package/out/candidate-fts.d.ts.map +1 -1
  151. package/out/candidate-fts.js +1 -1
  152. package/out/candidate-fts.js.map +1 -1
  153. package/out/candidate-importance.d.ts +16 -16
  154. package/out/candidate-importance.d.ts.map +1 -1
  155. package/out/candidate-importance.js +46 -51
  156. package/out/candidate-importance.js.map +1 -1
  157. package/out/candidate-lookup.d.ts +16 -14
  158. package/out/candidate-lookup.d.ts.map +1 -1
  159. package/out/candidate-lookup.js +67 -63
  160. package/out/candidate-lookup.js.map +1 -1
  161. package/out/candidate-schema.d.ts +6 -6
  162. package/out/candidate-schema.d.ts.map +1 -1
  163. package/out/candidate-schema.js +1 -1
  164. package/out/candidate-schema.js.map +1 -1
  165. package/out/candidate-scoring.d.ts +7 -7
  166. package/out/candidate-scoring.d.ts.map +1 -1
  167. package/out/candidate-scoring.js +10 -14
  168. package/out/candidate-scoring.js.map +1 -1
  169. package/out/capital-schema.d.ts +3 -3
  170. package/out/capital-schema.d.ts.map +1 -1
  171. package/out/capital-schema.js +2 -2
  172. package/out/capital-schema.js.map +1 -1
  173. package/out/capitals.d.ts +1 -1
  174. package/out/capitals.d.ts.map +1 -1
  175. package/out/capitals.js +2 -2
  176. package/out/capitals.js.map +1 -1
  177. package/out/coincident-roles.d.ts +7 -6
  178. package/out/coincident-roles.d.ts.map +1 -1
  179. package/out/coincident-roles.js +2 -4
  180. package/out/coincident-roles.js.map +1 -1
  181. package/out/{convention.d.ts → convention/index.d.ts} +4 -4
  182. package/out/convention/index.d.ts.map +1 -0
  183. package/out/{convention.js → convention/index.js} +2 -2
  184. package/out/convention/index.js.map +1 -0
  185. package/out/{convention-schema.d.ts → convention/schema.d.ts} +2 -2
  186. package/out/convention/schema.d.ts.map +1 -0
  187. package/out/{convention-schema.js → convention/schema.js} +3 -3
  188. package/out/convention/schema.js.map +1 -0
  189. package/out/coverage-manifest-schema.d.ts +8 -8
  190. package/out/coverage-manifest-schema.d.ts.map +1 -1
  191. package/out/coverage-manifest-schema.js +5 -4
  192. package/out/coverage-manifest-schema.js.map +1 -1
  193. package/out/currency-backfill.d.ts +51 -7
  194. package/out/currency-backfill.d.ts.map +1 -1
  195. package/out/currency-backfill.js +65 -49
  196. package/out/currency-backfill.js.map +1 -1
  197. package/out/env.d.ts +43 -0
  198. package/out/env.d.ts.map +1 -0
  199. package/out/env.js +48 -0
  200. package/out/env.js.map +1 -0
  201. package/out/exact-match.d.ts +5 -5
  202. package/out/exact-match.d.ts.map +1 -1
  203. package/out/exact-match.js +10 -11
  204. package/out/exact-match.js.map +1 -1
  205. package/out/extracts.d.ts +114 -0
  206. package/out/extracts.d.ts.map +1 -0
  207. package/out/{sharding.js → extracts.js} +38 -38
  208. package/out/extracts.js.map +1 -0
  209. package/out/{fst-autocomplete.d.ts → fst/autocomplete.d.ts} +2 -2
  210. package/out/fst/autocomplete.d.ts.map +1 -0
  211. package/out/{fst-autocomplete.js → fst/autocomplete.js} +3 -3
  212. package/out/fst/autocomplete.js.map +1 -0
  213. package/out/{fst-builder.d.ts → fst/builder.d.ts} +5 -5
  214. package/out/fst/builder.d.ts.map +1 -0
  215. package/out/{fst-builder.js → fst/builder.js} +14 -13
  216. package/out/fst/builder.js.map +1 -0
  217. package/out/{fst-deserialize-web.d.ts → fst/deserialize-web.d.ts} +3 -3
  218. package/out/fst/deserialize-web.d.ts.map +1 -0
  219. package/out/{fst-deserialize-web.js → fst/deserialize-web.js} +10 -74
  220. package/out/fst/deserialize-web.js.map +1 -0
  221. package/out/fst/format.d.ts +80 -0
  222. package/out/fst/format.d.ts.map +1 -0
  223. package/out/fst/format.js +91 -0
  224. package/out/fst/format.js.map +1 -0
  225. package/out/{fst-freshness.d.ts → fst/freshness.d.ts} +9 -13
  226. package/out/fst/freshness.d.ts.map +1 -0
  227. package/out/{fst-freshness.js → fst/freshness.js} +40 -73
  228. package/out/fst/freshness.js.map +1 -0
  229. package/out/fst/index.d.ts +14 -0
  230. package/out/fst/index.d.ts.map +1 -0
  231. package/out/fst/index.js +14 -0
  232. package/out/fst/index.js.map +1 -0
  233. package/out/{fst-matcher.d.ts → fst/matcher.d.ts} +2 -2
  234. package/out/fst/matcher.d.ts.map +1 -0
  235. package/out/{fst-matcher.js → fst/matcher.js} +1 -1
  236. package/out/fst/matcher.js.map +1 -0
  237. package/out/{fst-serialize.d.ts → fst/serialize.d.ts} +5 -10
  238. package/out/fst/serialize.d.ts.map +1 -0
  239. package/out/{fst-serialize.js → fst/serialize.js} +18 -98
  240. package/out/fst/serialize.js.map +1 -0
  241. package/out/{fst-types.d.ts → fst/types.d.ts} +4 -3
  242. package/out/fst/types.d.ts.map +1 -0
  243. package/out/{fst-types.js → fst/types.js} +1 -1
  244. package/out/fst/types.js.map +1 -0
  245. package/out/{fts.d.ts → fts/index.d.ts} +16 -9
  246. package/out/fts/index.d.ts.map +1 -0
  247. package/out/{fts.js → fts/index.js} +16 -11
  248. package/out/fts/index.js.map +1 -0
  249. package/out/{fts-query.d.ts → fts/query.d.ts} +2 -2
  250. package/out/fts/query.d.ts.map +1 -0
  251. package/out/{fts-query.js → fts/query.js} +1 -1
  252. package/out/fts/query.js.map +1 -0
  253. package/out/{geonames-aliases.d.ts → geonames/aliases.d.ts} +8 -6
  254. package/out/geonames/aliases.d.ts.map +1 -0
  255. package/out/{geonames-aliases.js → geonames/aliases.js} +7 -7
  256. package/out/geonames/aliases.js.map +1 -0
  257. package/out/geonames/index.d.ts +8 -0
  258. package/out/geonames/index.d.ts.map +1 -0
  259. package/out/geonames/index.js +8 -0
  260. package/out/geonames/index.js.map +1 -0
  261. package/out/{geonames-postal.d.ts → geonames/postal.d.ts} +10 -8
  262. package/out/geonames/postal.d.ts.map +1 -0
  263. package/out/{geonames-postal.js → geonames/postal.js} +9 -9
  264. package/out/geonames/postal.js.map +1 -0
  265. package/out/index.d.ts +32 -32
  266. package/out/index.d.ts.map +1 -1
  267. package/out/index.js +24 -24
  268. package/out/index.js.map +1 -1
  269. package/out/interpolation.d.ts +11 -10
  270. package/out/interpolation.d.ts.map +1 -1
  271. package/out/interpolation.js +20 -20
  272. package/out/interpolation.js.map +1 -1
  273. package/out/lookup.d.ts +22 -21
  274. package/out/lookup.d.ts.map +1 -1
  275. package/out/lookup.js +103 -113
  276. package/out/lookup.js.map +1 -1
  277. package/out/name-score.d.ts.map +1 -1
  278. package/out/name-score.js.map +1 -1
  279. package/out/nsul/index.d.ts +8 -0
  280. package/out/nsul/index.d.ts.map +1 -0
  281. package/out/nsul/index.js +8 -0
  282. package/out/nsul/index.js.map +1 -0
  283. package/out/nsul/lookup.d.ts +83 -0
  284. package/out/nsul/lookup.d.ts.map +1 -0
  285. package/out/nsul/lookup.js +80 -0
  286. package/out/nsul/lookup.js.map +1 -0
  287. package/out/nsul/schema.d.ts +100 -0
  288. package/out/nsul/schema.d.ts.map +1 -0
  289. package/out/nsul/schema.js +78 -0
  290. package/out/nsul/schema.js.map +1 -0
  291. package/out/place-importance-schema.d.ts +5 -6
  292. package/out/place-importance-schema.d.ts.map +1 -1
  293. package/out/place-importance-schema.js +3 -4
  294. package/out/place-importance-schema.js.map +1 -1
  295. package/out/poi/index.d.ts +8 -0
  296. package/out/poi/index.d.ts.map +1 -0
  297. package/out/poi/index.js +8 -0
  298. package/out/poi/index.js.map +1 -0
  299. package/out/{poi-lookup.d.ts → poi/lookup.d.ts} +8 -10
  300. package/out/poi/lookup.d.ts.map +1 -0
  301. package/out/{poi-lookup.js → poi/lookup.js} +14 -18
  302. package/out/poi/lookup.js.map +1 -0
  303. package/out/{poi-schema.d.ts → poi/schema.d.ts} +4 -4
  304. package/out/poi/schema.d.ts.map +1 -0
  305. package/out/{poi-schema.js → poi/schema.js} +1 -1
  306. package/out/poi/schema.js.map +1 -0
  307. package/out/polygon-schema.d.ts.map +1 -1
  308. package/out/polygon-schema.js.map +1 -1
  309. package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +6 -5
  310. package/out/postal/city-alias-lookup.d.ts.map +1 -0
  311. package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +11 -15
  312. package/out/postal/city-alias-lookup.js.map +1 -0
  313. package/out/{postal-city-alias-schema.d.ts → postal/city-alias-schema.d.ts} +1 -1
  314. package/out/{postal-city-alias-schema.d.ts.map → postal/city-alias-schema.d.ts.map} +1 -1
  315. package/out/{postal-city-alias-schema.js → postal/city-alias-schema.js} +1 -1
  316. package/out/{postal-city-alias-schema.js.map → postal/city-alias-schema.js.map} +1 -1
  317. package/out/{postal-city-candidate-schema.d.ts → postal/city-candidate-schema.d.ts} +3 -3
  318. package/out/{postal-city-candidate-schema.d.ts.map → postal/city-candidate-schema.d.ts.map} +1 -1
  319. package/out/{postal-city-candidate-schema.js → postal/city-candidate-schema.js} +2 -2
  320. package/out/{postal-city-candidate-schema.js.map → postal/city-candidate-schema.js.map} +1 -1
  321. package/out/postal/index.d.ts +9 -0
  322. package/out/postal/index.d.ts.map +1 -0
  323. package/out/postal/index.js +9 -0
  324. package/out/postal/index.js.map +1 -0
  325. package/out/postcode-point-lookup.d.ts +10 -10
  326. package/out/postcode-point-lookup.d.ts.map +1 -1
  327. package/out/postcode-point-lookup.js +13 -13
  328. package/out/postcode-point-lookup.js.map +1 -1
  329. package/out/primary-preference.d.ts +15 -7
  330. package/out/primary-preference.d.ts.map +1 -1
  331. package/out/primary-preference.js +28 -12
  332. package/out/primary-preference.js.map +1 -1
  333. package/out/proximity-rerank.d.ts +2 -2
  334. package/out/proximity-rerank.d.ts.map +1 -1
  335. package/out/proximity-rerank.js +2 -2
  336. package/out/proximity-rerank.js.map +1 -1
  337. package/out/ranking-weights.d.ts +15 -3
  338. package/out/ranking-weights.d.ts.map +1 -1
  339. package/out/ranking-weights.js +21 -3
  340. package/out/ranking-weights.js.map +1 -1
  341. package/out/region-keys.d.ts +8 -8
  342. package/out/region-keys.d.ts.map +1 -1
  343. package/out/region-keys.js +9 -9
  344. package/out/region-keys.js.map +1 -1
  345. package/out/reverse.d.ts +6 -6
  346. package/out/reverse.d.ts.map +1 -1
  347. package/out/reverse.js +20 -29
  348. package/out/reverse.js.map +1 -1
  349. package/out/schema.d.ts +9 -0
  350. package/out/schema.d.ts.map +1 -1
  351. package/out/schema.js.map +1 -1
  352. package/out/search-fetch.d.ts +12 -10
  353. package/out/search-fetch.d.ts.map +1 -1
  354. package/out/search-fetch.js +21 -20
  355. package/out/search-fetch.js.map +1 -1
  356. package/out/sqlite-convention-source.d.ts +7 -7
  357. package/out/sqlite-convention-source.d.ts.map +1 -1
  358. package/out/sqlite-convention-source.js +5 -5
  359. package/out/sqlite-convention-source.js.map +1 -1
  360. package/out/sqlite-utils.d.ts +8 -9
  361. package/out/sqlite-utils.d.ts.map +1 -1
  362. package/out/sqlite-utils.js +6 -10
  363. package/out/sqlite-utils.js.map +1 -1
  364. package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +6 -6
  365. package/out/{street-centroid-schema.d.ts.map → street/centroid-schema.d.ts.map} +1 -1
  366. package/out/{street-centroid-schema.js → street/centroid-schema.js} +5 -5
  367. package/out/{street-centroid-schema.js.map → street/centroid-schema.js.map} +1 -1
  368. package/out/{street-centroid.d.ts → street/centroid.d.ts} +7 -7
  369. package/out/street/centroid.d.ts.map +1 -0
  370. package/out/{street-centroid.js → street/centroid.js} +13 -19
  371. package/out/street/centroid.js.map +1 -0
  372. package/out/street/index.d.ts +13 -0
  373. package/out/street/index.d.ts.map +1 -0
  374. package/out/street/index.js +13 -0
  375. package/out/street/index.js.map +1 -0
  376. package/out/{street-morphology-fst-builder.d.ts → street/morphology-fst-builder.d.ts} +4 -4
  377. package/out/street/morphology-fst-builder.d.ts.map +1 -0
  378. package/out/{street-morphology-fst-builder.js → street/morphology-fst-builder.js} +18 -13
  379. package/out/street/morphology-fst-builder.js.map +1 -0
  380. package/out/{street-morphology-fst-loader.d.ts → street/morphology-fst-loader.d.ts} +5 -5
  381. package/out/street/morphology-fst-loader.d.ts.map +1 -0
  382. package/out/{street-morphology-fst-loader.js → street/morphology-fst-loader.js} +11 -10
  383. package/out/street/morphology-fst-loader.js.map +1 -0
  384. package/out/{street-name-lookup.d.ts → street/name-lookup.d.ts} +4 -7
  385. package/out/street/name-lookup.d.ts.map +1 -0
  386. package/out/{street-name-lookup.js → street/name-lookup.js} +9 -23
  387. package/out/street/name-lookup.js.map +1 -0
  388. package/out/{street-normalize.d.ts → street/normalize.d.ts} +38 -15
  389. package/out/street/normalize.d.ts.map +1 -0
  390. package/out/{street-normalize.js → street/normalize.js} +73 -17
  391. package/out/street/normalize.js.map +1 -0
  392. package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +8 -8
  393. package/out/{street-segment-schema.d.ts.map → street/segment-schema.d.ts.map} +1 -1
  394. package/out/{street-segment-schema.js → street/segment-schema.js} +4 -4
  395. package/out/{street-segment-schema.js.map → street/segment-schema.js.map} +1 -1
  396. package/out/types.d.ts +18 -12
  397. package/out/types.d.ts.map +1 -1
  398. package/out/types.js.map +1 -1
  399. package/out/unified-schema.d.ts +5 -4
  400. package/out/unified-schema.d.ts.map +1 -1
  401. package/out/unified-schema.js +15 -18
  402. package/out/unified-schema.js.map +1 -1
  403. package/out/uprn/existence.d.ts +53 -0
  404. package/out/uprn/existence.d.ts.map +1 -0
  405. package/out/uprn/existence.js +61 -0
  406. package/out/uprn/existence.js.map +1 -0
  407. package/out/uprn/index.d.ts +9 -0
  408. package/out/uprn/index.d.ts.map +1 -0
  409. package/out/uprn/index.js +9 -0
  410. package/out/uprn/index.js.map +1 -0
  411. package/out/{uprn-lookup.d.ts → uprn/lookup.d.ts} +4 -4
  412. package/out/uprn/lookup.d.ts.map +1 -0
  413. package/out/{uprn-lookup.js → uprn/lookup.js} +11 -14
  414. package/out/uprn/lookup.js.map +1 -0
  415. package/out/{uprn-schema.d.ts → uprn/schema.d.ts} +4 -4
  416. package/out/uprn/schema.d.ts.map +1 -0
  417. package/out/{uprn-schema.js → uprn/schema.js} +4 -4
  418. package/out/uprn/schema.js.map +1 -0
  419. package/out/weights-overlay-linker.d.ts +184 -26
  420. package/out/weights-overlay-linker.d.ts.map +1 -1
  421. package/out/weights-overlay-linker.js +339 -86
  422. package/out/weights-overlay-linker.js.map +1 -1
  423. package/package.json +465 -269
  424. package/address-point.ts +0 -218
  425. package/candidate/shard-fold.ts +0 -137
  426. package/out/address-point-interpolation.d.ts.map +0 -1
  427. package/out/address-point-interpolation.js.map +0 -1
  428. package/out/address-point-schema.d.ts.map +0 -1
  429. package/out/address-point-schema.js.map +0 -1
  430. package/out/address-point.d.ts.map +0 -1
  431. package/out/address-point.js +0 -140
  432. package/out/address-point.js.map +0 -1
  433. package/out/ancestry-backfill.d.ts.map +0 -1
  434. package/out/ancestry-backfill.js.map +0 -1
  435. package/out/ancestry.d.ts.map +0 -1
  436. package/out/ancestry.js.map +0 -1
  437. package/out/candidate/shard-fold.d.ts +0 -31
  438. package/out/candidate/shard-fold.d.ts.map +0 -1
  439. package/out/candidate/shard-fold.js +0 -104
  440. package/out/candidate/shard-fold.js.map +0 -1
  441. package/out/convention-schema.d.ts.map +0 -1
  442. package/out/convention-schema.js.map +0 -1
  443. package/out/convention.d.ts.map +0 -1
  444. package/out/convention.js.map +0 -1
  445. package/out/fst-autocomplete.d.ts.map +0 -1
  446. package/out/fst-autocomplete.js.map +0 -1
  447. package/out/fst-builder.d.ts.map +0 -1
  448. package/out/fst-builder.js.map +0 -1
  449. package/out/fst-deserialize-web.d.ts.map +0 -1
  450. package/out/fst-deserialize-web.js.map +0 -1
  451. package/out/fst-freshness.d.ts.map +0 -1
  452. package/out/fst-freshness.js.map +0 -1
  453. package/out/fst-matcher.d.ts.map +0 -1
  454. package/out/fst-matcher.js.map +0 -1
  455. package/out/fst-serialize.d.ts.map +0 -1
  456. package/out/fst-serialize.js.map +0 -1
  457. package/out/fst-types.d.ts.map +0 -1
  458. package/out/fst-types.js.map +0 -1
  459. package/out/fts-query.d.ts.map +0 -1
  460. package/out/fts-query.js.map +0 -1
  461. package/out/fts.d.ts.map +0 -1
  462. package/out/fts.js.map +0 -1
  463. package/out/geonames-aliases.d.ts.map +0 -1
  464. package/out/geonames-aliases.js.map +0 -1
  465. package/out/geonames-postal.d.ts.map +0 -1
  466. package/out/geonames-postal.js.map +0 -1
  467. package/out/poi-lookup.d.ts.map +0 -1
  468. package/out/poi-lookup.js.map +0 -1
  469. package/out/poi-schema.d.ts.map +0 -1
  470. package/out/poi-schema.js.map +0 -1
  471. package/out/postal-city-alias-lookup.d.ts.map +0 -1
  472. package/out/postal-city-alias-lookup.js.map +0 -1
  473. package/out/sharding.d.ts +0 -114
  474. package/out/sharding.d.ts.map +0 -1
  475. package/out/sharding.js.map +0 -1
  476. package/out/street-centroid.d.ts.map +0 -1
  477. package/out/street-centroid.js.map +0 -1
  478. package/out/street-morphology-fst-builder.d.ts.map +0 -1
  479. package/out/street-morphology-fst-builder.js.map +0 -1
  480. package/out/street-morphology-fst-loader.d.ts.map +0 -1
  481. package/out/street-morphology-fst-loader.js.map +0 -1
  482. package/out/street-name-lookup.d.ts.map +0 -1
  483. package/out/street-name-lookup.js.map +0 -1
  484. package/out/street-normalize.d.ts.map +0 -1
  485. package/out/street-normalize.js.map +0 -1
  486. package/out/uprn-lookup.d.ts.map +0 -1
  487. package/out/uprn-lookup.js.map +0 -1
  488. package/out/uprn-schema.d.ts.map +0 -1
  489. package/out/uprn-schema.js.map +0 -1
  490. package/weights-overlay-linker.ts +0 -377
  491. /package/{name-score.ts → lib/name-score.ts} +0 -0
  492. /package/{polygon-schema.ts → lib/polygon-schema.ts} +0 -0
  493. /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
@@ -4,10 +4,10 @@
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
6
  * Node-side {@link PlaceLookup} over the byte-range CANDIDATE table (`build-candidate.ts`) — the
7
- * SAME gazetteer the browser demo resolves against ({@link WOFCandidateTableLookup} in
8
- * `docs/src/shared/httpvfs-resolver.ts`), but reading a LOCAL `candidate.db` via `node:sqlite`
9
- * instead of sql.js-httpvfs. This is what makes the server/CLI resolver match the demo: one
10
- * lookup surface, one artifact, one ranking.
7
+ * SAME gazetteer the browser runtime resolves against ({@link WOFCandidateTableLookup} in
8
+ * `packages/resolver-wof-wasm/lib/httpvfs/resolver.ts`), but reading a LOCAL `candidate.db` via
9
+ * `node:sqlite` instead of sql.js-httpvfs. This is what makes the server/CLI resolver match the
10
+ * browser: one lookup surface, one artifact, one ranking.
11
11
  *
12
12
  * The query is a single contiguous probe on the `WITHOUT ROWID` B-tree keyed `(name_key,
13
13
  * country_id, region_id, placetype_id, neg_rank, spr_id)`. `name_key` is the SHARED
@@ -23,16 +23,18 @@
23
23
  * `bbox` field on {@link FindPlaceQuery}).
24
24
  */
25
25
 
26
- import { DatabaseSync } from "node:sqlite"
27
-
28
- import { jaroWinkler, levenshteinSimilarity } from "@mailwoman/match/comparators"
29
26
  import {
30
27
  expandPlacetypeFilter,
31
- partitionByContainment,
32
28
  type Ancestor,
33
29
  type GazetteerArtifactCoverage,
34
- } from "@mailwoman/resolver"
30
+ referentialFromPopulation,
31
+ } from "@mailwoman/core/resolver"
32
+ import { allRows } from "@mailwoman/core/utils"
33
+ import { jaroWinkler, levenshteinSimilarity } from "@mailwoman/match/comparators"
34
+ import { partitionByContainment } from "@mailwoman/resolver"
35
35
  import { haversineKm } from "@mailwoman/spatial"
36
+ import { DatabaseClient } from "@mailwoman/sqlite/client"
37
+ import type { PathBuilderLike } from "path-ts"
36
38
 
37
39
  import {
38
40
  CANDIDATE_ANCESTOR_TABLE,
@@ -40,31 +42,30 @@ import {
40
42
  intervalContains,
41
43
  type CandidateAncestorTable,
42
44
  type IntervalLabel,
43
- } from "./candidate-ancestors-schema.ts"
44
- import { CANDIDATE_FTS_TABLE } from "./candidate-fts.ts"
45
- import type { CandidateTable, CountryCodeTable, PlacetypeCodeTable } from "./candidate-schema.ts"
46
- import { readGazetteerCoverageManifest } from "./coverage-manifest-schema.ts"
47
- import { referentialFromPopulation } from "./place-importance-schema.ts"
48
- import { POSTAL_CITY_CANDIDATE_TABLE, type PostalCityCandidateTable } from "./postal-city-candidate-schema.ts"
49
- import { rankByPrimaryPreference, type RankedRow, RERANK_FETCH } from "./primary-preference.ts"
50
- import { applyProximityRerank } from "./proximity-rerank.ts"
51
- import { REGION_CLASS_PLACETYPES, regionQualifierProbeKeys } from "./region-keys.ts"
52
- import { allRows, hasColumn, hasTable } from "./sqlite-utils.ts"
53
- import { type NameKey, normalizeLocalityForKey, stripLocalityQualifier } from "./street-normalize.ts"
54
- import type { FindPlaceQuery, PlaceCandidate, PlaceLookup, WOFPlacetype } from "./types.ts"
55
-
56
- export { rankByPrimaryPreference } from "./primary-preference.ts"
57
- export type { RankedRow } from "./primary-preference.ts"
45
+ } from "#candidate-ancestors-schema"
46
+ import { CANDIDATE_FTS_TABLE } from "#candidate-fts"
47
+ import type { CandidateDatabase, CandidateTable, CountryCodeTable, PlacetypeCodeTable } from "#candidate-schema"
48
+ import { readGazetteerCoverageManifest } from "#coverage-manifest-schema"
49
+ import { POSTAL_CITY_CANDIDATE_TABLE, type PostalCityCandidateTable } from "#postal/city-candidate-schema"
50
+ import { rankByPrimaryPreference, type RankedRow, RERANK_FETCH } from "#primary-preference"
51
+ import { applyProximityRerank } from "#proximity-rerank"
52
+ import { REGION_CLASS_PLACETYPES, regionQualifierProbeKeys } from "#region-keys"
53
+ import { hasColumn, hasTable } from "#sqlite-utils"
54
+ import { type NameKey, normalizeLocalityForKey, stripLocalityQualifier } from "#street/normalize"
55
+ import type { FindPlaceQuery, PlaceCandidate, PlaceLookup, WOFPlacetype } from "#types"
56
+
57
+ export { rankByPrimaryPreference } from "#primary-preference"
58
+ export type { RankedRow } from "#primary-preference"
58
59
 
59
60
  export interface WOFCandidateTableLookupOpts {
60
61
  /**
61
62
  * Path to a `candidate.db` built by `build-candidate.ts`. Opened read-only.
62
63
  */
63
- databasePath?: string
64
+ databasePath?: PathBuilderLike
64
65
  /**
65
66
  * Pre-opened handle (tests / shared connections). Mutually exclusive with `databasePath`.
66
67
  */
67
- database?: DatabaseSync
68
+ database?: DatabaseClient<CandidateDatabase>
68
69
  /**
69
70
  * #1882 opt-in: exempt `name_role = 'variant'` aliases — the holder's own primary name in another orthography,
70
71
  * stamped by the build's own-name detector — from the cross-country primary-preference penalty. No-ops on an artifact
@@ -126,12 +127,12 @@ function wordFuzzySimilarity(a: string, b: string): number {
126
127
  }
127
128
 
128
129
  /**
129
- * Postcode-containment re-rank gate radius (km) — the SAME value the resolver's country pass measures at
130
- * (`POSTCODE_COUNTRY_COHERENCE_GATE_KM`, resolver/postcode-country-coherence.ts): a locality within this distance of
131
- * the postcode's own centroid counts as "containing" it. One number, two passes — a divergence here would make the two
132
- * mechanisms disagree about what is proximal.
130
+ * Postcode-containment re-rank check radius (km) — the SAME value the resolver's country pass measures at
131
+ * (`POSTCODE_COUNTRY_COHERENCE_THRESHOLD_KM`, resolver/postcode-country-coherence.ts): a locality within this distance
132
+ * of the postcode's own centroid counts as "containing" it. One number, two passes — a divergence here would make the
133
+ * two mechanisms disagree about what is proximal.
133
134
  */
134
- const POSTCODE_CONTAINMENT_GATE_KM = 25
135
+ const POSTCODE_CONTAINMENT_THRESHOLD_KM = 25
135
136
 
136
137
  /**
137
138
  * Unpadded character-trigrams of `s`, OR'd into an FTS5 trigram MATCH query (each quoted so FTS treats it as a literal
@@ -156,9 +157,13 @@ function ftsTrigramQuery(s: string): string {
156
157
  * Node {@link PlaceLookup} over `candidate.db`. Drop-in for {@link WOFSQLitePlaceLookup} in `createWOFResolver(backend)`
157
158
  * — same `findPlace` contract, population-first ranking.
158
159
  */
159
- export class WOFCandidateTableLookup implements PlaceLookup {
160
- #db: DatabaseSync
161
- #ownsDB: boolean
160
+ export class WOFCandidateTableLookup implements PlaceLookup, Disposable {
161
+ #db: DatabaseClient<CandidateDatabase>
162
+ /**
163
+ * Resources this instance opened. A connection handed in by a caller is NOT in here, so disposal cannot reach it —
164
+ * ownership is membership rather than a flag a later branch has to check.
165
+ */
166
+ readonly #resources = new DisposableStack()
162
167
  readonly #countryToID = new Map<string, number>()
163
168
  readonly #idToCountry = new Map<number, string>()
164
169
  readonly #placetypeToID = new Map<string, number>()
@@ -167,29 +172,29 @@ export class WOFCandidateTableLookup implements PlaceLookup {
167
172
  * Prepared `(name_key, postcode)` probe for the #741 postal-city side-index — `undefined` when the
168
173
  * `postal_city_candidate` table isn't present, so a candidate.db built without it is byte-stable.
169
174
  */
170
- readonly #postalCityProbe: ReturnType<DatabaseSync["prepare"]> | undefined
175
+ readonly #postalCityProbe: ReturnType<DatabaseClient["prepare"]> | undefined
171
176
  /**
172
177
  * Prepared FTS5-trigram MATCH probe for the typo-tolerant fallback — `undefined` when the `candidate_fts` index isn't
173
178
  * present, so a candidate.db built without it is byte-stable (the fuzzy path is skipped, exactly like today).
174
179
  */
175
- readonly #ftsProbe: ReturnType<DatabaseSync["prepare"]> | undefined
180
+ readonly #ftsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
176
181
  /**
177
- * Prepared UNFILTERED existence probe (`name_key` present anywhere, ignoring country/placetype/bbox). Gates the fuzzy
178
- * fallback: fuzzy is a TYPO corrector, so it engages only when the name doesn't exist in the gazetteer at all. A name
179
- * that DOES exist but missed under the active filter is a filter miss (e.g. a placer misroute "Vienna, Austria"→IT),
180
- * not a spelling miss — fuzzing it would scrape an unrelated same-country place and defeat the cascade's
181
- * country-agnostic retry. Prepared only alongside `#ftsProbe`.
182
+ * Prepared UNFILTERED existence probe (`name_key` present anywhere, ignoring country/placetype/bbox). Checks the
183
+ * fuzzy fallback: fuzzy is a TYPO corrector, so it engages only when the name doesn't exist in the gazetteer at all.
184
+ * A name that DOES exist but missed under the active filter is a filter miss (e.g. a placer misroute "Vienna,
185
+ * Austria"→IT), not a spelling miss — fuzzing it would scrape an unrelated same-country place and defeat the
186
+ * cascade's country-agnostic retry. Prepared only alongside `#ftsProbe`.
182
187
  */
183
- readonly #nameKeyExistsProbe: ReturnType<DatabaseSync["prepare"]> | undefined
188
+ readonly #nameKeyExistsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
184
189
  /**
185
190
  * Facts this candidate DB declares about itself — the coverage manifest (`country_coverage` + `country_bbox`) the
186
191
  * gazetteer build emits, read once at open. `undefined` when the artifact predates the manifest, so every consumer
187
- * (the hard-country coverage gate, guard-B plausibility) falls back to its code constants byte-identically.
192
+ * (the hard-country coverage check, guard-B plausibility) falls back to its code constants byte-identically.
188
193
  */
189
194
  readonly artifactCoverage: GazetteerArtifactCoverage | undefined
190
195
  /**
191
196
  * `", importance"` when this artifact carries the #28 fame column, `""` when it does not — spliced into the probe's
192
- * SELECT list. Existence-gated exactly like `#ftsProbe` and `#postalCityProbe` above, and for the same reason: a
197
+ * SELECT list. Existence-restricted exactly like `#ftsProbe` and `#postalCityProbe` above, and for the same reason: a
193
198
  * candidate.db built before the column is a valid artifact, and naming a column it lacks would turn a stale gazetteer
194
199
  * into `no such column` on the first keystroke rather than into "no fame signal", which is what it is.
195
200
  */
@@ -208,22 +213,22 @@ export class WOFCandidateTableLookup implements PlaceLookup {
208
213
  /**
209
214
  * Prepared chain probe over the `candidate_ancestor` sidecar — `undefined` when the artifact predates it.
210
215
  */
211
- readonly #ancestorsProbe: ReturnType<DatabaseSync["prepare"]> | undefined
216
+ readonly #ancestorsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
212
217
  readonly #ancestorsCache = new Map<number, Ancestor[]>()
213
218
  /**
214
219
  * Prepared interval-label probe over `candidate_interval` — `undefined` when the artifact predates the sidecar, which
215
- * is what makes the admin-containment re-rank (#1717 stage 2) capability-gated: without it,
220
+ * is what makes the admin-containment re-rank (#1717 stage 2) capability-restricted: without it,
216
221
  * `FindPlaceQuery.regionQualifier` is ignored, no candidate carries a `containedByQualifier` stamp, and the resolver
217
- * walk reports the lever `unavailable` instead of silently dead.
222
+ * walk reports the change `unavailable` instead of silently dead.
218
223
  */
219
- readonly #intervalProbe: ReturnType<DatabaseSync["prepare"]> | undefined
224
+ readonly #intervalProbe: ReturnType<DatabaseClient["prepare"]> | undefined
220
225
  readonly #intervalCache = new Map<number, IntervalLabel | null>()
221
226
  /**
222
227
  * Prepared qualifier probe: the region-band rows (plus `country` — the region SLOT can hold a mislabeled country
223
228
  * name, "Moscow, Russia" parses region="Russia") for one folded qualifier key. `undefined` when the artifact lacks
224
229
  * the sidecar or the placetype dictionary lacks the band entirely.
225
230
  */
226
- readonly #qualifierProbe: ReturnType<DatabaseSync["prepare"]> | undefined
231
+ readonly #qualifierProbe: ReturnType<DatabaseClient["prepare"]> | undefined
227
232
  /**
228
233
  * The ancestor lineage of a resolved place — nearest-first (locality-tier → county → region → … → country), the same
229
234
  * order the FTS backend's `ancestorLineage` serves, read from the `candidate_ancestor` sidecar in one clustered
@@ -240,10 +245,8 @@ export class WOFCandidateTableLookup implements PlaceLookup {
240
245
  constructor(opts: WOFCandidateTableLookupOpts) {
241
246
  if (opts.database) {
242
247
  this.#db = opts.database
243
- this.#ownsDB = false
244
248
  } else if (opts.databasePath) {
245
- this.#db = new DatabaseSync(opts.databasePath, { readOnly: true })
246
- this.#ownsDB = true
249
+ this.#db = this.#resources.use(new DatabaseClient<CandidateDatabase>(opts.databasePath, { readOnly: true }))
247
250
  } else {
248
251
  throw new Error("WOFCandidateTableLookup needs `databasePath` or `database`")
249
252
  }
@@ -285,7 +288,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
285
288
  this.#variantAliasExemption = opts.variantAliasExemption === true
286
289
  this.#roleSelect = this.#hasNameRole ? ", name_role" : ""
287
290
 
288
- // Ancestors sidecar (#1717): existence-gated like the probes above, and the CAPABILITY gates with
291
+ // Ancestors sidecar (#1717): existence-restricted like the probes above, and the CAPABILITY checks with
289
292
  // it — see the `ancestors` property doc for why an older artifact must read as "no ancestors()"
290
293
  // rather than as a method that answers [] everywhere.
291
294
  if (hasTable(this.#db, CANDIDATE_ANCESTOR_TABLE)) {
@@ -297,7 +300,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
297
300
  this.ancestors = (id) => this.#ancestorLineage(id)
298
301
  }
299
302
 
300
- // Admin-containment re-rank (#1717 stage 2): gated on the interval half of the sidecar (built in
303
+ // Admin-containment re-rank (#1717 stage 2): conditioned on the interval half of the sidecar (built in
301
304
  // the same pass as the closure rows; probed separately so a hand-degraded artifact degrades
302
305
  // truthfully) AND on the placetype dictionary carrying the qualifier band at all.
303
306
  if (this.#ancestorsProbe && hasTable(this.#db, CANDIDATE_INTERVAL_TABLE)) {
@@ -314,7 +317,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
314
317
  }
315
318
  }
316
319
 
317
- // Coverage manifest (survey candidate #2): the artifact's own coverage facts, existence-gated like
320
+ // Coverage manifest (survey candidate #2): the artifact's own coverage facts, existence-restricted like
318
321
  // the probes above — a candidate.db built before the manifest reads `undefined` and consumers keep
319
322
  // their code-constant fallbacks byte-identically.
320
323
  this.artifactCoverage = readGazetteerCoverageManifest(this.#db)
@@ -396,7 +399,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
396
399
  * Is `sprID` contained by ANY of the qualifier's rows? Interval first — {@link intervalContains}, O(1), reflexive —
397
400
  * then the closure rows where intervals abstain: the interval forest encodes only the CANONICAL parent per place, so
398
401
  * a `false` there means "not contained along the canonical hierarchy", and the chain probe (one clustered read of
399
- * ≤{@link MAX_ANCESTOR_DEPTH} rows) is the complete record that settles it.
402
+ * ≤{@link MAX_ANCESTOR_DEPTH} rows) is the complete record that determines the result.
400
403
  */
401
404
  #containedByQualifier(sprID: number, qualifierIDs: ReadonlySet<number>, qualifierLabels: IntervalLabel[]): boolean {
402
405
  if (qualifierIDs.has(sprID)) return true
@@ -491,7 +494,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
491
494
  // cannot reach a neighbourhood-tier namesake, so a CONTAINED one is structurally invisible no matter
492
495
  // how the list reorders — the Astoria class: Queens' Astoria is a WOF neighbourhood, and the walk
493
496
  // answered the Oregon locality under `qualifier="NY"` because nothing in the pool sat under NY. The
494
- // widening is injection-only and triple-gated: the band is explicit (neighbourhood/macrohood/microhood
497
+ // widening is injection-only and triple-conditioned: the band is explicit (neighbourhood/macrohood/microhood
495
498
  // — never region or country tiers), admission still requires the sidecar's containment proof, and only
496
499
  // primary-keyed rows enter (an alias-keyed neighbourhood is the #1626 scrape class). Recall can only
497
500
  // widen, and only toward rows the qualifier vouches for. `opts.shapeFilters`' bbox clause is
@@ -601,7 +604,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
601
604
 
602
605
  // #741: postcode-keyed postal-city alias. An exact `(name_key, postcode)` hit resolves a
603
606
  // user-typed POSTAL city ("Antioch", 37013) to the geographic locality the postcode sits in
604
- // ("Nashville"), bypassing the population/region ranking that can't see the postcode. Gated on
607
+ // ("Nashville"), bypassing the population/region ranking that can't see the postcode. Conditioned on
605
608
  // the side-index being present, a postcode in the query, and a locality-tier request — so the
606
609
  // common (no-postcode / non-locality) path is untouched. A hit short-circuits: the postcode is
607
610
  // an exact, high-confidence disambiguator, so we return the single geographic locality.
@@ -632,7 +635,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
632
635
  // SHAPE subset (placetype/bbox/primary — everything but the country scope) is kept separately
633
636
  // because the admin-containment injection probe (#1717 stage 2) runs under the shape conds
634
637
  // WITHOUT the country: bypassing a locale-inferred country scope for a qualifier-vouched
635
- // candidate is the lever's whole point, and it is the one filter injection may cross.
638
+ // candidate is the change's whole point and the one filter injection may cross.
636
639
  const filters: string[] = []
637
640
  const filterParams: Array<string | number> = []
638
641
  const shapeFilters: string[] = []
@@ -667,7 +670,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
667
670
  }
668
671
 
669
672
  // The re-reading guard (#1632, the #1626 rationale generalized to the caller): a probe whose surface
670
- // is a token cut out of a longer classified span never NAMED an alias, so alias-keyed rows must not
673
+ // is a token taken out of a longer classified span never NAMED an alias, so alias-keyed rows must not
671
674
  // answer it — 'Savile Row''s token 'Row' resolved Rhu, Scotland (585 km) through the village's
672
675
  // historical-name alias key. Whole-input bare probes never set this, keeping the exonym recall the
673
676
  // #1546 note protects (Москва's alias rows answer 'Moscow').
@@ -763,7 +766,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
763
766
  // the same on either backend. The country/placetype/bbox/region filters still apply via `probe`.
764
767
  // Skipped when the index is absent (byte-stable for an older candidate.db).
765
768
  //
766
- // Gate: only when the name doesn't exist in the gazetteer AT ALL (unfiltered). A name that exists
769
+ // Condition: only when the name doesn't exist in the gazetteer AT ALL (unfiltered). A name that exists
767
770
  // but missed under the active country/placetype/bbox filter is a FILTER miss, not a spelling miss
768
771
  // — fuzzing it scrapes an unrelated same-filter place ("Vienna, Austria" misrouted to IT would
769
772
  // pull a tiny Italian name_key near Siena) and masks the cascade's country-agnostic retry that
@@ -821,7 +824,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
821
824
 
822
825
  let rows = cascade(regionParentID)
823
826
  // #1731: whether the rows the caller receives came from the UNSCOPED fallback below — the backend's
824
- // interior gate the resolver-side trace (#1721) cannot otherwise see. Stamped onto every returned
827
+ // interior check the resolver-side trace (#1721) cannot otherwise see. Stamped onto every returned
825
828
  // place, because the re-admission path is exactly where a wrong-instance namesake enters.
826
829
  let regionScopeMiss = false
827
830
 
@@ -838,8 +841,8 @@ export class WOFCandidateTableLookup implements PlaceLookup {
838
841
  // holds 75001, not the one that holds a 75001-free namesake). The resolver sends this flag on locality
839
842
  // lookups when `ResolveOpts.postcodeContainmentCoherence` is on. Strictly beneath the #741 postal-city
840
843
  // short-circuit above — an exact (name, postcode) hit IS the answer and outranks any re-rank — and after
841
- // the region-scope fallback, so it sees the final row set. Rows within the gate sort by distance first;
842
- // the out-gate tail keeps its original population-first order. No in-gate row, or no postcode row in
844
+ // the region-scope fallback, so it sees the final row set. Rows within the radius sort by distance first;
845
+ // the out-of-radius tail keeps its original population-first order. No in-radius row, or no postcode row in
843
846
  // the candidate table → unchanged (byte-identical to the flag-off path).
844
847
  if (
845
848
  query.postcode &&
@@ -850,32 +853,32 @@ export class WOFCandidateTableLookup implements PlaceLookup {
850
853
  const anchor = this.#postcodeAnchor(query.postcode, query.country)
851
854
 
852
855
  if (anchor) {
853
- const inGate: Array<{ row: RankedRow<CandidateRow>; distanceKm: number }> = []
854
- const outGate: RankedRow<CandidateRow>[] = []
856
+ const insideThreshold: Array<{ row: RankedRow<CandidateRow>; distanceKm: number }> = []
857
+ const outsideThreshold: RankedRow<CandidateRow>[] = []
855
858
 
856
859
  for (const row of rows) {
857
860
  const distanceKm = haversineKm(anchor.lat, anchor.lon, Number(row.latitude), Number(row.longitude))
858
861
 
859
- if (distanceKm <= POSTCODE_CONTAINMENT_GATE_KM) {
860
- inGate.push({ row, distanceKm })
862
+ if (distanceKm <= POSTCODE_CONTAINMENT_THRESHOLD_KM) {
863
+ insideThreshold.push({ row, distanceKm })
861
864
  } else {
862
- outGate.push(row)
865
+ outsideThreshold.push(row)
863
866
  }
864
867
  }
865
868
 
866
- if (inGate.length) {
869
+ if (insideThreshold.length) {
867
870
  // oxlint-disable-next-line unicorn/no-array-sort -- sorts a freshly-built array; toSorted would double-allocate on a hot path
868
- inGate.sort((a, b) => a.distanceKm - b.distanceKm)
869
- rows = [...inGate.map(({ row }) => row), ...outGate]
871
+ insideThreshold.sort((a, b) => a.distanceKm - b.distanceKm)
872
+ rows = [...insideThreshold.map(({ row }) => row), ...outsideThreshold]
870
873
  }
871
874
  }
872
875
  }
873
876
 
874
877
  // Admin-containment re-rank (#1717 stage 2): LAST, on the final row set — the qualifier is the
875
878
  // address's outermost explicit statement, so its partition outranks the postcode-proximity order
876
- // above (contained rows keep that order among themselves). Capability-gated on the sidecar
879
+ // above (contained rows keep that order among themselves). Capability-conditioned on the sidecar
877
880
  // (`#qualifierProbe`); when the artifact predates it, `regionQualifier` is ignored, no stamp is
878
- // written, and the resolver walk reports the lever `unavailable`.
881
+ // written, and the resolver walk reports the change `unavailable`.
879
882
  if (query.regionQualifier?.trim() && this.#qualifierProbe && this.#wantsLocality(query.placetype)) {
880
883
  rows = this.#applyAdminContainment(rows, query.regionQualifier.trim(), query.country, {
881
884
  nameKey,
@@ -893,13 +896,13 @@ export class WOFCandidateTableLookup implements PlaceLookup {
893
896
  id: Number(row.spr_id),
894
897
  name: String(row.name ?? ""),
895
898
  placetype: (this.#idToPlacetype.get(Number(row.placetype_id)) ?? "") as WOFPlacetype,
896
- // Surfaced so the cascade can country-gate a postcode by the resolved locality (an ambiguous
899
+ // Surfaced so the cascade can country-restrict a postcode by the resolved locality (an ambiguous
897
900
  // international postcode like 10115 = Berlin DE AND New York US must not out-resolve the city).
898
901
  country: this.#idToCountry.get(Number(row.country_id)) ?? "",
899
902
  lat: Number(row.latitude),
900
903
  lon: Number(row.longitude),
901
904
  // `score` stays the RAW population rank (`-neg_rank`) — it feeds the resolver walk's absolute
902
- // `minWinningScore` gate (`resolve.ts`), which must see real prominence, never a penalized value.
905
+ // `minWinningScore` floor (`resolve.ts`), which must see real prominence, never a penalized value.
903
906
  score: -Number(row.neg_rank),
904
907
  // `prominence` carries the bounded cross-country primary preference (the effective, penalty-adjusted
905
908
  // rank). The walk ORDERS candidates by `prominence ?? score` (`resolve.ts`), so this is what makes the
@@ -921,6 +924,9 @@ export class WOFCandidateTableLookup implements PlaceLookup {
921
924
  // asked (a `regionQualifier` query over a sidecar-bearing artifact); its absence is what
922
925
  // the resolver walk reports as `unavailable` (meaning-of-zero).
923
926
  ...(row.containedByQualifier === undefined ? {} : { containedByQualifier: row.containedByQualifier }),
927
+ // #1893 — the exemption's firing mark, carried only when the ranker actually spared this row
928
+ // the cross-country penalty (see RankedRow.variantExempted).
929
+ ...(row.variantExempted ? { variantAliasExempted: true as const } : {}),
924
930
  // The two-score split's carry (ROAD_TO_V9 §2). `referential` names the prominence this
925
931
  // backend has always ordered by — `neg_rank` IS `-log10(population + 1)`, so the score and
926
932
  // the sort key are two readings of the same number.
@@ -965,9 +971,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
965
971
  return candidates
966
972
  }
967
973
 
968
- close(): void {
969
- if (this.#ownsDB) {
970
- this.#db.close()
971
- }
974
+ [Symbol.dispose](): void {
975
+ this.#resources[Symbol.dispose]()
972
976
  }
973
977
  }
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Typed schema for the byte-range CANDIDATE gazetteer (`candidate.db`) — the single source of truth
7
7
  * for the columns shared by the BUILDER ({@link buildCandidateTable}) and the READERS (the Node
8
- * {@link WOFCandidateTableLookup} + the browser `httpvfs-resolver.ts`). Before this module each
8
+ * {@link WOFCandidateTableLookup} + the browser `@mailwoman/resolver-wof-wasm/httpvfs/resolver`). Before this module each
9
9
  * side hand-wrote the column list; a rename in one place broke the other at runtime. Now the
10
10
  * contract is a Kysely `Database` interface (`new DatabaseClient<CandidateDatabase>(...)` for
11
11
  * typed inserts) plus the table DDL as strings — so a column change is a compile error on every
@@ -17,14 +17,14 @@
17
17
 
18
18
  import { sql, type Kysely } from "kysely"
19
19
 
20
- import type { CandidateAncestorsDatabase } from "./candidate-ancestors-schema.ts"
21
- import type { CapitalTable } from "./capital-schema.ts"
22
- import type { NameKey } from "./street-normalize.ts"
20
+ import type { CandidateAncestorsDatabase } from "#candidate-ancestors-schema"
21
+ import type { CapitalTable } from "#capital-schema"
22
+ import type { NameKey } from "#street/normalize"
23
23
 
24
24
  /**
25
25
  * One candidate row. `name_key` + the four small int keys + `neg_rank` + `spr_id` form the clustered primary key; the
26
26
  * rest is denormalized so a resolve is one probe (no join to `spr`). Coordinates + bbox + name are nullable at the SQL
27
- * level (a postcode shard row may lack a bbox).
27
+ * level (a postcode extract row may lack a bbox).
28
28
  */
29
29
  export interface CandidateTable {
30
30
  /**
@@ -99,7 +99,7 @@ export interface CandidateTable {
99
99
  * core.
100
100
  *
101
101
  * NULL = no role detected. The column is WRITE-ONLY in this build generation: no ranking consumer reads it — a rank
102
- * penalty is its own future, D-rule-gated step with the `gloss_key` board as tripwire.
102
+ * penalty is its own future, D-rule-conditional step with the `gloss_key` board as regression check.
103
103
  */
104
104
  name_role: string | null
105
105
  }
@@ -7,15 +7,15 @@
7
7
  * ordered — the weighted-sum score and the exact-match tiering that ranks over it.
8
8
  */
9
9
 
10
- import type { DatabaseSync } from "node:sqlite"
11
-
10
+ import { compareReferential, referentialFromPopulation } from "@mailwoman/core/resolver"
12
11
  import { haversineKm } from "@mailwoman/spatial"
12
+ import type { DatabaseClient } from "@mailwoman/sqlite/client"
13
13
 
14
- import { exactMatchIDs, officialNameIDs } from "./exact-match.ts"
15
- import { compareReferential, referentialFromPopulation } from "./place-importance-schema.ts"
16
- import type { RankingWeights } from "./ranking-weights.ts"
17
- import type { RawSearchRow } from "./search-fetch.ts"
18
- import type { FindPlaceQuery, PlaceCandidate, WOFPlacetype } from "./types.ts"
14
+ import { exactMatchIDs, officialNameIDs } from "#exact-match"
15
+ import { foldQueryText } from "#fts/index"
16
+ import { populationBoostTerm, type RankingWeights } from "#ranking-weights"
17
+ import type { RawSearchRow } from "#search-fetch"
18
+ import type { FindPlaceQuery, PlaceCandidate, WOFPlacetype } from "#types"
19
19
 
20
20
  /**
21
21
  * Score one raw FTS row into a `PlaceCandidate`: the weighted sum over the negated BM25 baseline, the placetype /
@@ -95,14 +95,8 @@ export function candidateFromSearchRow(
95
95
 
96
96
  // Population boost: capped at `populationBoost` magnitude at `10^populationScaleLog10`
97
97
  // people. Missing population → no contribution. Never penalizes.
98
- let popTerm = 0
99
-
100
- if (row.population !== null && row.population > 0 && weights.populationScaleLog10 > 0) {
101
- const popLog = Math.log10(1 + row.population)
102
- const popFraction = Math.min(1, popLog / weights.populationScaleLog10)
103
- popTerm = weights.populationBoost * popFraction
104
- score += popTerm
105
- }
98
+ const popTerm = populationBoostTerm(row.population, weights)
99
+ score += popTerm
106
100
 
107
101
  // Combined prominence for the exact-tier sort when proximity hints are present: population
108
102
  // and nearness in the SAME additive units, so the map view / the user's location can win a
@@ -154,13 +148,13 @@ export function candidateFromSearchRow(
154
148
  }
155
149
 
156
150
  /**
157
- * Order `candidates` IN PLACE — the exact-match tier first when the shard can answer the name probes, otherwise plain
151
+ * Order `candidates` IN PLACE — the exact-match tier first when the extract can answer the name probes, otherwise plain
158
152
  * weighted-score order. Every candidate is stamped with its `exactMatch` flag on the way through.
159
153
  */
160
- export function rankCandidates(
154
+ export function rankCandidates<DB>(
161
155
  candidates: PlaceCandidate[],
162
156
  options: {
163
- db: DatabaseSync
157
+ db: DatabaseClient<DB>
164
158
  schemaName: string
165
159
  query: FindPlaceQuery
166
160
  weights: RankingWeights
@@ -204,12 +198,11 @@ export function rankCandidates(
204
198
  // widen recall, not to tie primaries. ME→Maine is untouched: 'ME' name-exact-matches
205
199
  // nothing, so the alias sub-tier still decides there. Population orders within each
206
200
  // sub-tier as before.
207
- const norm = (v: string): string => v.toLowerCase().trim().replaceAll(/\s+/g, " ")
208
- const needle = norm(query.text)
201
+ const needle = foldQueryText(query.text)
209
202
 
210
203
  // #936 option 3: an OFFICIAL name (preferred form in an official language of the place's
211
204
  // country, `names.official = 1`) counts as the place's own name for the sub-tier — "Åbo" is
212
- // Turku's name, not merely its alias. Floor-gated on the holder's population (see the
205
+ // Turku's name, not merely its alias. Floor-conditioned on the holder's population (see the
213
206
  // RankingWeights docstring for the measured 100k boundary). officialIDs ⊆ exactIDs by
214
207
  // construction (official rows are names rows), so only the sub-tier KIND changes.
215
208
  const officialIDs = weights.officialNameExact
@@ -226,7 +219,7 @@ export function rankCandidates(
226
219
  const kind = (c: PlaceCandidate): number => {
227
220
  if (!exactIDs.has(c.id as number)) return 0
228
221
 
229
- if (norm(String(c.name ?? "")) === needle) return 2
222
+ if (foldQueryText(String(c.name ?? "")) === needle) return 2
230
223
 
231
224
  return officialIDs?.has(c.id as number) ? 2 : 1
232
225
  }
@@ -14,13 +14,12 @@
14
14
  * keeps the coordinate radius from promoting a capital's same-name neighbours (`capitals.ts`).
15
15
  */
16
16
 
17
- import type { DatabaseSync } from "node:sqlite"
18
-
19
- import { tryParsingJSON } from "@mailwoman/core/objects"
17
+ import { tryParsingJSON } from "@mailwoman/core/json"
18
+ import type { DatabaseClient } from "@mailwoman/sqlite/client"
20
19
  import type { Kysely } from "kysely"
21
20
 
22
- import type { CapitalPoint } from "./capitals.ts"
23
- import { hasTable } from "./sqlite-utils.ts"
21
+ import type { CapitalPoint } from "#capitals"
22
+ import { hasTable } from "#sqlite-utils"
24
23
 
25
24
  /**
26
25
  * The table name the builder writes and the reader probes — one word, singular, matching the artifact's other reference
@@ -63,7 +62,7 @@ export async function createCapitalTable<DB extends { capital: CapitalTable }>(d
63
62
  * back to its next source rather than treating an old artifact as "no capitals" (the meaning-of-zero rule: a missing
64
63
  * table is UNMEASURED, an empty one is a finding).
65
64
  */
66
- export function readCapitalPoints(db: DatabaseSync): CapitalPoint[] | null {
65
+ export function readCapitalPoints<DB>(db: DatabaseClient<DB>): CapitalPoint[] | null {
67
66
  if (!hasTable(db, CAPITAL_TABLE)) return null
68
67
 
69
68
  const points: CapitalPoint[] = []
@@ -12,7 +12,7 @@
12
12
  * Matching is an IDENTITY test with three conjuncts: same country, within
13
13
  * {@link CAPITAL_MATCH_RADIUS_KM} of the reference point, and the candidate's own folded name a
14
14
  * member of the reference entry's folded name set (name + romanization + the source's alternate
15
- * names, so exonym rows — "Vienna" for Wien — still match). All three are load-bearing. The
15
+ * names, so exonym rows — "Vienna" for Wien — still match). All three are required. The
16
16
  * iteration-1 board run matched on country + coordinate alone, and the 25 km radius promoted
17
17
  * capital-ADJACENT namesakes instead of capitals: North Salt Lake beside the Utah seat, a Gujarat
18
18
  * Indiranagar beside Gandhinagar, Via delle Parti beside Perugia. The name set is what makes the
@@ -21,7 +21,7 @@
21
21
 
22
22
  import { haversineKm } from "@mailwoman/spatial"
23
23
 
24
- import { normalizeLocalityForKey } from "./street-normalize.ts"
24
+ import { normalizeLocalityForKey } from "#street/normalize"
25
25
 
26
26
  /**
27
27
  * Capital status of one candidate: national capital, admin-1 seat, or neither. Numeric so the resolver's promotion can
@@ -38,13 +38,13 @@
38
38
  * be wired as a post-step of the main `scripts/build-unified-wof.ts`.
39
39
  */
40
40
 
41
- import type { DatabaseSync } from "node:sqlite"
42
-
43
- import type { CoincidentLocality } from "@mailwoman/resolver"
41
+ import type { CoincidentLocality } from "@mailwoman/core/resolver"
42
+ import { allRows } from "@mailwoman/core/utils"
44
43
  import { haversineKm } from "@mailwoman/spatial"
44
+ import type { DatabaseClient } from "@mailwoman/sqlite/client"
45
+ import { tableExists } from "@mailwoman/sqlite/introspection"
45
46
 
46
- import { allRows } from "./sqlite-utils.ts"
47
-
47
+ import type { WOFDatabase } from "#schema"
48
48
  /**
49
49
  * Table of places that hold more than one admin role — a locality that is also its county seat. Written by the
50
50
  * gazetteer build, read by the resolver when a coincident locality has to be chosen.
@@ -105,16 +105,12 @@ interface CandidateRow {
105
105
  pop: number
106
106
  }
107
107
 
108
- function tableExists(db: DatabaseSync, name: string): boolean {
109
- return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name = ?").get(name)
110
- }
111
-
112
108
  /**
113
109
  * Derive the coincident-roles relation into `db`. Additive — only creates/replaces the `coincident_roles` table; never
114
110
  * touches `spr`/`names`/`ancestors`. Idempotent.
115
111
  */
116
112
  export function buildCoincidentRoles(
117
- db: DatabaseSync,
113
+ db: DatabaseClient<WOFDatabase>,
118
114
  opts: BuildCoincidentRolesOpts = {}
119
115
  ): BuildCoincidentRolesResult {
120
116
  const start = Date.now()
@@ -215,7 +211,7 @@ export function buildCoincidentRoles(
215
211
  /**
216
212
  * True iff the relation table exists. Used by the resolver to decide whether completion can run.
217
213
  */
218
- export function coincidentRolesExists(db: DatabaseSync): boolean {
214
+ export function coincidentRolesExists<DB>(db: DatabaseClient<DB>): boolean {
219
215
  return tableExists(db, COINCIDENT_ROLES_TABLE)
220
216
  }
221
217
 
@@ -224,7 +220,7 @@ export function coincidentRolesExists(db: DatabaseSync): boolean {
224
220
  * MULTIPLE same-name descendants; the consumer disambiguates (min distance → population → abstain). Returns an empty
225
221
  * map when the table is absent.
226
222
  */
227
- export function loadCoincidentRoles(db: DatabaseSync): Map<number, CoincidentRole[]> {
223
+ export function loadCoincidentRoles<DB>(db: DatabaseClient<DB>): Map<number, CoincidentRole[]> {
228
224
  const map = new Map<number, CoincidentRole[]>()
229
225
 
230
226
  if (!coincidentRolesExists(db)) return map
@@ -269,7 +265,7 @@ export function loadCoincidentRoles(db: DatabaseSync): Map<number, CoincidentRol
269
265
  * {@link loadCoincidentRoles}, carrying the canonical name and coordinates each coincident locality resolves to.
270
266
  * Returns an empty map when the relation table is absent.
271
267
  */
272
- export function loadCoincidentLocalities(db: DatabaseSync): Map<number, CoincidentLocality[]> {
268
+ export function loadCoincidentLocalities<DB>(db: DatabaseClient<DB>): Map<number, CoincidentLocality[]> {
273
269
  const map = new Map<number, CoincidentLocality[]>()
274
270
 
275
271
  if (coincidentRolesExists(db)) {
@@ -21,7 +21,7 @@
21
21
  * source).
22
22
  */
23
23
 
24
- import type { FindPlaceQuery, PlaceCandidate } from "./types.ts"
24
+ import type { FindPlaceQuery, PlaceCandidate } from "#types"
25
25
 
26
26
  /**
27
27
  * Soft-scoring weights for the `postcode_area_resolution` strategy: `pc·S_pc + name·S_name + pop·S_pop`.
@@ -76,13 +76,13 @@ export const WORLD_DEFAULT: ResolvedConvention = {
76
76
  export const BUILTIN_STRATEGY_NAMES = ["postcode_area_resolution", "fallback_fuzzy_name_match"] as const
77
77
 
78
78
  /**
79
- * Table name for the convention asset (#290). Carried here so the build script, the runtime source, and the shard
79
+ * Table name for the convention asset (#290). Carried here so the build script, the runtime source, and the extract
80
80
  * auto-detect all agree.
81
81
  */
82
82
  export const ADDRESS_CONVENTION_TABLE = "address_convention"
83
83
 
84
84
  /**
85
- * A named resolution primitive. Returns `null` to abstain (gate unmet / no data) → the dispatcher tries the next
85
+ * A named resolution primitive. Returns `null` to abstain (condition unmet / no data) → the dispatcher tries the next
86
86
  * strategy; returns an array (possibly empty) to claim the result.
87
87
  */
88
88
  export type Strategy = (query: FindPlaceQuery, convention: ResolvedConvention) => Promise<PlaceCandidate[] | null>