@mailwoman/resolver-wof-sqlite 9.0.0 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/README.md +28 -9
  2. package/address-point-interpolation.ts +18 -8
  3. package/address-point-schema.ts +18 -6
  4. package/address-point.ts +111 -18
  5. package/ancestry.ts +9 -6
  6. package/build-candidate.ts +287 -157
  7. package/build-slim.ts +3 -3
  8. package/candidate/alias-bags.ts +54 -0
  9. package/candidate/ancestors-sidecar.ts +206 -0
  10. package/candidate/country-display-names.ts +79 -0
  11. package/candidate/name-roles.ts +237 -0
  12. package/candidate/own-name.ts +146 -0
  13. package/candidate/place-attrs.ts +44 -0
  14. package/candidate/shard-fold.ts +137 -0
  15. package/candidate-ancestors-schema.ts +195 -0
  16. package/candidate-fts.ts +4 -2
  17. package/candidate-importance.ts +228 -0
  18. package/candidate-lookup.ts +564 -174
  19. package/candidate-schema.ts +60 -3
  20. package/candidate-scoring.ts +268 -0
  21. package/capital-schema.ts +90 -0
  22. package/capitals.ts +148 -0
  23. package/coincident-roles.ts +69 -10
  24. package/convention-schema.ts +72 -0
  25. package/convention.ts +2 -2
  26. package/coverage-manifest-schema.ts +7 -7
  27. package/currency-backfill.ts +249 -0
  28. package/exact-match.ts +104 -0
  29. package/fst-autocomplete.ts +105 -122
  30. package/fst-builder.ts +39 -47
  31. package/fst-deserialize-web.ts +43 -7
  32. package/fst-freshness.ts +2 -2
  33. package/fst-serialize.ts +68 -12
  34. package/fst-types.ts +35 -1
  35. package/fts-query.ts +1 -1
  36. package/fts.ts +16 -4
  37. package/geonames-postal.ts +2 -2
  38. package/index.ts +26 -14
  39. package/interpolation.ts +113 -19
  40. package/lookup.ts +118 -560
  41. package/name-score.ts +6 -4
  42. package/out/address-point-interpolation.d.ts.map +1 -1
  43. package/out/address-point-interpolation.js +13 -7
  44. package/out/address-point-interpolation.js.map +1 -1
  45. package/out/address-point-schema.d.ts +16 -6
  46. package/out/address-point-schema.d.ts.map +1 -1
  47. package/out/address-point-schema.js.map +1 -1
  48. package/out/address-point.d.ts.map +1 -1
  49. package/out/address-point.js +70 -14
  50. package/out/address-point.js.map +1 -1
  51. package/out/ancestry.d.ts +2 -2
  52. package/out/ancestry.d.ts.map +1 -1
  53. package/out/ancestry.js +5 -6
  54. package/out/ancestry.js.map +1 -1
  55. package/out/build-candidate.d.ts +108 -0
  56. package/out/build-candidate.d.ts.map +1 -1
  57. package/out/build-candidate.js +151 -120
  58. package/out/build-candidate.js.map +1 -1
  59. package/out/build-slim.d.ts +1 -1
  60. package/out/build-slim.js +3 -3
  61. package/out/build-slim.js.map +1 -1
  62. package/out/candidate/alias-bags.d.ts +17 -0
  63. package/out/candidate/alias-bags.d.ts.map +1 -0
  64. package/out/candidate/alias-bags.js +39 -0
  65. package/out/candidate/alias-bags.js.map +1 -0
  66. package/out/candidate/ancestors-sidecar.d.ts +33 -0
  67. package/out/candidate/ancestors-sidecar.d.ts.map +1 -0
  68. package/out/candidate/ancestors-sidecar.js +140 -0
  69. package/out/candidate/ancestors-sidecar.js.map +1 -0
  70. package/out/candidate/country-display-names.d.ts +35 -0
  71. package/out/candidate/country-display-names.d.ts.map +1 -0
  72. package/out/candidate/country-display-names.js +59 -0
  73. package/out/candidate/country-display-names.js.map +1 -0
  74. package/out/candidate/name-roles.d.ts +55 -0
  75. package/out/candidate/name-roles.d.ts.map +1 -0
  76. package/out/candidate/name-roles.js +165 -0
  77. package/out/candidate/name-roles.js.map +1 -0
  78. package/out/candidate/own-name.d.ts +50 -0
  79. package/out/candidate/own-name.d.ts.map +1 -0
  80. package/out/candidate/own-name.js +132 -0
  81. package/out/candidate/own-name.js.map +1 -0
  82. package/out/candidate/place-attrs.d.ts +43 -0
  83. package/out/candidate/place-attrs.d.ts.map +1 -0
  84. package/out/candidate/place-attrs.js +15 -0
  85. package/out/candidate/place-attrs.js.map +1 -0
  86. package/out/candidate/shard-fold.d.ts +31 -0
  87. package/out/candidate/shard-fold.d.ts.map +1 -0
  88. package/out/candidate/shard-fold.js +104 -0
  89. package/out/candidate/shard-fold.js.map +1 -0
  90. package/out/candidate-ancestors-schema.d.ts +150 -0
  91. package/out/candidate-ancestors-schema.d.ts.map +1 -0
  92. package/out/candidate-ancestors-schema.js +123 -0
  93. package/out/candidate-ancestors-schema.js.map +1 -0
  94. package/out/candidate-fts.d.ts +4 -2
  95. package/out/candidate-fts.d.ts.map +1 -1
  96. package/out/candidate-fts.js +4 -2
  97. package/out/candidate-fts.js.map +1 -1
  98. package/out/candidate-importance.d.ts +132 -0
  99. package/out/candidate-importance.d.ts.map +1 -0
  100. package/out/candidate-importance.js +174 -0
  101. package/out/candidate-importance.js.map +1 -0
  102. package/out/candidate-lookup.d.ts +22 -37
  103. package/out/candidate-lookup.d.ts.map +1 -1
  104. package/out/candidate-lookup.js +446 -132
  105. package/out/candidate-lookup.js.map +1 -1
  106. package/out/candidate-schema.d.ts +52 -4
  107. package/out/candidate-schema.d.ts.map +1 -1
  108. package/out/candidate-schema.js +8 -0
  109. package/out/candidate-schema.js.map +1 -1
  110. package/out/candidate-scoring.d.ts +34 -0
  111. package/out/candidate-scoring.d.ts.map +1 -0
  112. package/out/candidate-scoring.js +200 -0
  113. package/out/candidate-scoring.js.map +1 -0
  114. package/out/capital-schema.d.ts +51 -0
  115. package/out/capital-schema.d.ts.map +1 -0
  116. package/out/capital-schema.js +63 -0
  117. package/out/capital-schema.js.map +1 -0
  118. package/out/capitals.d.ts +69 -0
  119. package/out/capitals.d.ts.map +1 -0
  120. package/out/capitals.js +98 -0
  121. package/out/capitals.js.map +1 -0
  122. package/out/coincident-roles.d.ts +7 -0
  123. package/out/coincident-roles.d.ts.map +1 -1
  124. package/out/coincident-roles.js +42 -8
  125. package/out/coincident-roles.js.map +1 -1
  126. package/out/convention-schema.d.ts +51 -0
  127. package/out/convention-schema.d.ts.map +1 -0
  128. package/out/convention-schema.js +34 -0
  129. package/out/convention-schema.js.map +1 -0
  130. package/out/convention.d.ts +1 -1
  131. package/out/convention.js +2 -2
  132. package/out/coverage-manifest-schema.js +3 -7
  133. package/out/coverage-manifest-schema.js.map +1 -1
  134. package/out/currency-backfill.d.ts +46 -0
  135. package/out/currency-backfill.d.ts.map +1 -0
  136. package/out/currency-backfill.js +180 -0
  137. package/out/currency-backfill.js.map +1 -0
  138. package/out/exact-match.d.ts +25 -0
  139. package/out/exact-match.d.ts.map +1 -0
  140. package/out/exact-match.js +89 -0
  141. package/out/exact-match.js.map +1 -0
  142. package/out/fst-autocomplete.d.ts +24 -14
  143. package/out/fst-autocomplete.d.ts.map +1 -1
  144. package/out/fst-autocomplete.js +84 -100
  145. package/out/fst-autocomplete.js.map +1 -1
  146. package/out/fst-builder.d.ts.map +1 -1
  147. package/out/fst-builder.js +32 -40
  148. package/out/fst-builder.js.map +1 -1
  149. package/out/fst-deserialize-web.d.ts.map +1 -1
  150. package/out/fst-deserialize-web.js +36 -7
  151. package/out/fst-deserialize-web.js.map +1 -1
  152. package/out/fst-freshness.d.ts +2 -2
  153. package/out/fst-freshness.js +2 -2
  154. package/out/fst-serialize.d.ts +14 -4
  155. package/out/fst-serialize.d.ts.map +1 -1
  156. package/out/fst-serialize.js +60 -12
  157. package/out/fst-serialize.js.map +1 -1
  158. package/out/fst-types.d.ts +35 -1
  159. package/out/fst-types.d.ts.map +1 -1
  160. package/out/fts-query.js +1 -1
  161. package/out/fts-query.js.map +1 -1
  162. package/out/fts.d.ts +15 -4
  163. package/out/fts.d.ts.map +1 -1
  164. package/out/fts.js +15 -4
  165. package/out/fts.js.map +1 -1
  166. package/out/geonames-postal.d.ts +2 -2
  167. package/out/geonames-postal.js +2 -2
  168. package/out/index.d.ts +4 -2
  169. package/out/index.d.ts.map +1 -1
  170. package/out/index.js +3 -2
  171. package/out/index.js.map +1 -1
  172. package/out/interpolation.d.ts +8 -0
  173. package/out/interpolation.d.ts.map +1 -1
  174. package/out/interpolation.js +91 -19
  175. package/out/interpolation.js.map +1 -1
  176. package/out/lookup.d.ts +4 -5
  177. package/out/lookup.d.ts.map +1 -1
  178. package/out/lookup.js +102 -444
  179. package/out/lookup.js.map +1 -1
  180. package/out/name-score.d.ts +0 -10
  181. package/out/name-score.d.ts.map +1 -1
  182. package/out/name-score.js +6 -4
  183. package/out/name-score.js.map +1 -1
  184. package/out/place-importance-schema.d.ts +226 -0
  185. package/out/place-importance-schema.d.ts.map +1 -0
  186. package/out/place-importance-schema.js +288 -0
  187. package/out/place-importance-schema.js.map +1 -0
  188. package/out/poi-lookup.d.ts +1 -1
  189. package/out/poi-lookup.d.ts.map +1 -1
  190. package/out/poi-lookup.js +12 -13
  191. package/out/poi-lookup.js.map +1 -1
  192. package/out/poi-schema.d.ts +7 -3
  193. package/out/poi-schema.d.ts.map +1 -1
  194. package/out/poi-schema.js.map +1 -1
  195. package/out/polygon-schema.d.ts +37 -0
  196. package/out/polygon-schema.d.ts.map +1 -0
  197. package/out/polygon-schema.js +23 -0
  198. package/out/polygon-schema.js.map +1 -0
  199. package/out/postal-city-alias-lookup.d.ts +1 -1
  200. package/out/postal-city-alias-lookup.js +1 -1
  201. package/out/postal-city-candidate-schema.d.ts +2 -1
  202. package/out/postal-city-candidate-schema.d.ts.map +1 -1
  203. package/out/postal-city-candidate-schema.js.map +1 -1
  204. package/out/postcode-point-lookup.d.ts +1 -1
  205. package/out/postcode-point-lookup.js +1 -1
  206. package/out/primary-preference.d.ts +125 -0
  207. package/out/primary-preference.d.ts.map +1 -0
  208. package/out/primary-preference.js +138 -0
  209. package/out/primary-preference.js.map +1 -0
  210. package/out/proximity-rerank.d.ts +77 -0
  211. package/out/proximity-rerank.d.ts.map +1 -0
  212. package/out/proximity-rerank.js +86 -0
  213. package/out/proximity-rerank.js.map +1 -0
  214. package/out/region-keys.d.ts +47 -0
  215. package/out/region-keys.d.ts.map +1 -0
  216. package/out/region-keys.js +121 -0
  217. package/out/region-keys.js.map +1 -0
  218. package/out/reverse.d.ts.map +1 -1
  219. package/out/reverse.js +6 -9
  220. package/out/reverse.js.map +1 -1
  221. package/out/schema.d.ts +1 -1
  222. package/out/search-fetch.d.ts +57 -0
  223. package/out/search-fetch.d.ts.map +1 -0
  224. package/out/search-fetch.js +183 -0
  225. package/out/search-fetch.js.map +1 -0
  226. package/out/sharding.d.ts +3 -3
  227. package/out/sharding.js +1 -1
  228. package/out/sqlite-convention-source.d.ts +1 -1
  229. package/out/sqlite-convention-source.js +1 -1
  230. package/out/sqlite-utils.d.ts +31 -1
  231. package/out/sqlite-utils.d.ts.map +1 -1
  232. package/out/sqlite-utils.js +38 -0
  233. package/out/sqlite-utils.js.map +1 -1
  234. package/out/street-centroid-schema.d.ts +7 -2
  235. package/out/street-centroid-schema.d.ts.map +1 -1
  236. package/out/street-centroid-schema.js.map +1 -1
  237. package/out/street-centroid.d.ts.map +1 -1
  238. package/out/street-centroid.js +7 -7
  239. package/out/street-centroid.js.map +1 -1
  240. package/out/street-morphology-fst-builder.d.ts.map +1 -1
  241. package/out/street-morphology-fst-builder.js +5 -4
  242. package/out/street-morphology-fst-builder.js.map +1 -1
  243. package/out/street-normalize.d.ts +83 -9
  244. package/out/street-normalize.d.ts.map +1 -1
  245. package/out/street-normalize.js +177 -10
  246. package/out/street-normalize.js.map +1 -1
  247. package/out/street-segment-schema.d.ts +6 -2
  248. package/out/street-segment-schema.d.ts.map +1 -1
  249. package/out/street-segment-schema.js.map +1 -1
  250. package/out/types.d.ts +74 -1
  251. package/out/types.d.ts.map +1 -1
  252. package/out/unified-schema.d.ts +1 -1
  253. package/out/unified-schema.js +1 -1
  254. package/out/uprn-lookup.d.ts +85 -0
  255. package/out/uprn-lookup.d.ts.map +1 -0
  256. package/out/uprn-lookup.js +152 -0
  257. package/out/uprn-lookup.js.map +1 -0
  258. package/out/uprn-schema.d.ts +93 -0
  259. package/out/uprn-schema.d.ts.map +1 -0
  260. package/out/uprn-schema.js +78 -0
  261. package/out/uprn-schema.js.map +1 -0
  262. package/out/weights-overlay-linker.d.ts +141 -0
  263. package/out/weights-overlay-linker.d.ts.map +1 -0
  264. package/out/weights-overlay-linker.js +259 -0
  265. package/out/weights-overlay-linker.js.map +1 -0
  266. package/package.json +296 -16
  267. package/place-importance-schema.ts +402 -0
  268. package/poi-lookup.ts +12 -13
  269. package/poi-schema.ts +8 -3
  270. package/polygon-schema.ts +47 -0
  271. package/postal-city-alias-lookup.ts +1 -1
  272. package/postal-city-candidate-schema.ts +3 -1
  273. package/postcode-point-lookup.ts +1 -1
  274. package/primary-preference.ts +207 -0
  275. package/proximity-rerank.ts +120 -0
  276. package/region-keys.ts +144 -0
  277. package/reverse.ts +17 -16
  278. package/schema.ts +1 -1
  279. package/search-fetch.ts +256 -0
  280. package/sharding.ts +3 -3
  281. package/sqlite-convention-source.ts +1 -1
  282. package/sqlite-utils.ts +63 -1
  283. package/street-centroid-schema.ts +8 -2
  284. package/street-centroid.ts +13 -8
  285. package/street-morphology-fst-builder.ts +5 -4
  286. package/street-normalize.ts +254 -24
  287. package/street-segment-schema.ts +7 -2
  288. package/types.ts +74 -1
  289. package/unified-schema.ts +1 -1
  290. package/uprn-lookup.ts +210 -0
  291. package/uprn-schema.ts +124 -0
  292. package/weights-overlay-linker.ts +377 -0
  293. package/geo.ts +0 -121
  294. package/out/geo.d.ts +0 -74
  295. package/out/geo.d.ts.map +0 -1
  296. package/out/geo.js +0 -71
  297. package/out/geo.js.map +0 -1
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Typed schema for `uprn.db` — the OS Open UPRN spatial layer: every GB Unique Property Reference
7
+ * Number with its WGS84 point, so mailwoman results can carry UPRN as an interoperability key
8
+ * beside our own `@mailwoman/address-id`. One rowid table keyed `uprn INTEGER PRIMARY KEY` (the
9
+ * rowid alias — the optimal shape for an integer-PK point table; `WITHOUT ROWID` buys nothing
10
+ * here), plus a secondary res-9 `h3_cell` index for the bounded nearest-point probe.
11
+ *
12
+ * ## Coordinates are OS's own WGS84 columns
13
+ *
14
+ * The source CSV publishes BOTH coordinate systems per row — OSGB36 eastings/northings AND WGS84
15
+ * `LATITUDE`/`LONGITUDE`. This layer stores OS's own lat/lon verbatim and never reconverts from
16
+ * eastings: `@mailwoman/spatial`'s `osgb36ToWGS84` is a 7-parameter Helmert with a measured p95 of
17
+ * 4.18 m, and re-deriving what the publisher already computed (with OSTN15, exactly) would replace
18
+ * their answer with a strictly worse one.
19
+ *
20
+ * ## Why `h3_cell` exists at all
21
+ *
22
+ * The layer contract requires every domain row to be addressable by at least one spine key —
23
+ * `writeLayerManifest` throws on a manifest that declares none — and UPRN is its own id space, not
24
+ * H3/WOF/address-id/street. The res-9 short cell (`shortCellToInt`, the same packing as poi.db and
25
+ * the OSM situs shards) is the spine that fits a point table, and its index doubles as the
26
+ * `nearestUPRN` ring probe.
27
+ *
28
+ * The DB also embeds the layer-contract tables from `@mailwoman/core/layers`; the builder
29
+ * (`packages/mailwoman/gazetteer-pipeline/uprn-layer.ts`) writes the manifest and per-res-6-cell
30
+ * coverage.
31
+ */
32
+ import { shortCellToInt } from "@mailwoman/spatial";
33
+ import { latLngToCell } from "h3-js";
34
+ /**
35
+ * Resolution the `uprn` table's `h3_cell` column is keyed at — the shared layer-spine resolution (poi.db, the OSM situs
36
+ * shards).
37
+ */
38
+ export const UPRN_H3_RESOLUTION = 9;
39
+ /**
40
+ * Resolution of the layer's `layer_coverage` cells — coarse, per the contract (matches poi.db).
41
+ */
42
+ export const UPRN_COVERAGE_H3_RESOLUTION = 6;
43
+ /**
44
+ * The full res-9 cell for a UPRN point — the ONE derivation both the builder and every consumer share, so a fixture
45
+ * built by a test and a row built by the real ingest can never disagree on which cell a coordinate keys to.
46
+ */
47
+ export function uprnFullCell(latitude, longitude) {
48
+ return latLngToCell(latitude, longitude, UPRN_H3_RESOLUTION);
49
+ }
50
+ /**
51
+ * The `h3_cell` column value for a UPRN point: {@link uprnFullCell} packed to the shared 48-bit short-cell integer.
52
+ */
53
+ export function uprnH3Cell(latitude, longitude) {
54
+ return shortCellToInt(uprnFullCell(latitude, longitude));
55
+ }
56
+ export async function createUPRNTable(db) {
57
+ await db.schema
58
+ .createTable("uprn")
59
+ .addColumn("uprn", "integer", (c) => c.primaryKey())
60
+ .addColumn("lat", "real", (c) => c.notNull())
61
+ .addColumn("lon", "real", (c) => c.notNull())
62
+ .addColumn("h3_cell", "integer", (c) => c.notNull())
63
+ .execute();
64
+ }
65
+ export async function createUPRNMetaTable(db) {
66
+ await db.schema
67
+ .createTable("uprn_meta")
68
+ .addColumn("key", "text", (c) => c.primaryKey())
69
+ .addColumn("value", "text", (c) => c.notNull())
70
+ .execute();
71
+ }
72
+ /**
73
+ * Secondary index for the `nearestUPRN` ring probe. Builders call this AFTER the bulk load (index-after-load).
74
+ */
75
+ export async function createUPRNIndexes(db) {
76
+ await db.schema.createIndex("uprn_h3_cell").on("uprn").column("h3_cell").execute();
77
+ }
78
+ //# sourceMappingURL=uprn-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uprn-schema.js","sourceRoot":"","sources":["../uprn-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,EAAE,cAAc,EAAe,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAGpC;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAEnC;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAA;AAuC5C;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,SAAiB;IAC/D,OAAO,YAAY,CAAC,QAAQ,EAAE,SAAS,EAAE,kBAAkB,CAAW,CAAA;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,SAAiB;IAC7D,OAAO,cAAc,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAA;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAwB;IAC7D,MAAM,EAAE,CAAC,MAAM;SACb,WAAW,CAAC,MAAM,CAAC;SACnB,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;SACnD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SAC5C,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SAC5C,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SACnD,OAAO,EAAE,CAAA;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EAAwB;IACjE,MAAM,EAAE,CAAC,MAAM;SACb,WAAW,CAAC,WAAW,CAAC;SACxB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;SAC/C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SAC9C,OAAO,EAAE,CAAA;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAwB;IAC/D,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAA;AACnF,CAAC"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ * Shared development tooling for weights overlays: the symlink primitives every overlay linker uses, and the
6
+ * placetype-pair index build.
7
+ */
8
+ /**
9
+ * Replicate `ln -sf SRC DEST` ATOMICALLY: symlink under a temp name, then rename over the destination. A plain
10
+ * unlink-then-symlink leaves a no-file window that concurrent vitest workers can hit mid-suite — bit CI on 2026-07-24.
11
+ * rename(2) replaces the destination atomically.
12
+ */
13
+ export declare function linkForce(src: string, dest: string): void;
14
+ /**
15
+ * Remove a leftover local file/symlink so the #1179 base-weights fallback engages.
16
+ */
17
+ export declare function removeIfPresent(dest: string): void;
18
+ /**
19
+ * Symlink one soft-feed sibling into an overlay, warning rather than failing when the source is absent.
20
+ *
21
+ * Every one of these artifacts is OPTIONAL by design — the runtime has a fallback for each, so a fresh worktree that
22
+ * has not built the gazetteer still geocodes. That is why the miss prints the consequence instead of throwing: the
23
+ * operator needs to know which channel just resolved OFF, not to have the link step abort.
24
+ */
25
+ export declare function linkSoftFeedSibling(source: string, destination: string, consequenceIfMissing: string): boolean;
26
+ /**
27
+ * What one pair-index overlay has to say about itself. Everything else is shared.
28
+ */
29
+ export interface PairIndexOverlay {
30
+ /**
31
+ * Workspace directory name, e.g. `neural-weights-de-de`.
32
+ */
33
+ packageDir: string;
34
+ /**
35
+ * ISO country code passed to `gazetteer pair-index --country`, and the suffix of the built artifact (`de` →
36
+ * `pair-index-de.bin`). NOT the locale tag: `en-in` builds `pair-index-in.bin`.
37
+ */
38
+ country: string;
39
+ /**
40
+ * Calibrated magnitudes the locale's bars were measured at. Baked into the artifact's PIX1 header, which is how the
41
+ * freshness check below notices a change to either.
42
+ */
43
+ delta: number;
44
+ transitionBeta: number;
45
+ }
46
+ /**
47
+ * The header fields a dev-weights freshness guard reads.
48
+ */
49
+ export interface PairIndexHeaderFields {
50
+ delta: number;
51
+ transitionBeta: number | undefined;
52
+ parentDelta: number | undefined;
53
+ schemaVersion: number;
54
+ /**
55
+ * One md5 per source the build read, in fold order. Empty on a header that recorded none.
56
+ */
57
+ sourceMD5s: string[];
58
+ }
59
+ /**
60
+ * Minimal PIX1 header reader — magic + header only, reimplemented so a data-only weights package gains no dependency on
61
+ * `@mailwoman/neural` (which pulls onnxruntime-node) to read a few fields. `neural/pair-index-resolver.ts`'s own header
62
+ * parse is the source of truth this must follow.
63
+ *
64
+ * Shared by the overlay build below AND by the four hand-written base linkers
65
+ * (`neural-weights-{en-us,en-gb,en-nz,fr-fr}/scripts/link-dev-weights.ts`), which each carried their own near-copy
66
+ * before 2026-08-04 — the ×5 clone the taste audit named, and the reason three of them were schema-blind while this one
67
+ * was not.
68
+ */
69
+ export declare function peekPairIndexHeaderFields(path: string): PairIndexHeaderFields;
70
+ /**
71
+ * Md5 of `path`, cached in a standard `md5sum`-format sidecar (`<hash> <filename>`) beside it so a multi-gigabyte
72
+ * source is hashed once per change rather than once per linker run. The sidecar is trusted only when at least as new as
73
+ * the source; a missing or stale sidecar recomputes and rewrites, so the cache self-heals.
74
+ *
75
+ * The shared home for the copies the base linkers (`en-us`, `en-gb`, `en-nz`) each carry — new callers import this one.
76
+ */
77
+ export declare function md5FileWithSidecar(path: string): Promise<string>;
78
+ /**
79
+ * The calibrated magnitudes a linker bakes into its artifact. `undefined` means the flag is NOT passed and the header
80
+ * carries no such key — a real state, distinct from zero (see `PairIndexHeader.parentDelta`), so the comparison below
81
+ * is `!==` against `undefined` rather than a truthiness test.
82
+ */
83
+ export interface PairIndexCalibration {
84
+ delta: number;
85
+ transitionBeta?: number;
86
+ parentDelta?: number;
87
+ }
88
+ /**
89
+ * Why an existing `pair-index-*.bin` is stale against `expected`, or `undefined` when its header matches. Covers the
90
+ * FORMAT (schemaVersion) and every calibrated magnitude; source-md5 freshness stays with the caller, because each base
91
+ * linker passes a different set of sources and only it knows what they are.
92
+ *
93
+ * One place so a magnitude added to the header cannot be checked by some linkers and not others — which is exactly how
94
+ * three of the four base linkers ended up unable to notice a schema bump.
95
+ */
96
+ export declare function pairIndexStaleReason(header: PairIndexHeaderFields, expected: PairIndexCalibration): string | undefined;
97
+ /**
98
+ * The PIX1 schema this tree's reader requires. MUST equal `KNOWN_SCHEMA_VERSION` in `neural/pair-index-resolver.ts` —
99
+ * they are two ends of one fact, and this copy exists only because a data-only overlay must not gain a dependency on
100
+ * `@mailwoman/neural` (onnxruntime-node) to read one header field. Bump BOTH in the same commit; a schema bump that
101
+ * leaves this behind makes every dev checkout rebuild-loop or serve an artifact the runtime refuses.
102
+ *
103
+ * The freshness guard must compare it: a guard that checks only delta + source md5 reads a format-obsolete binary as
104
+ * "current" and leaves every dev checkout with artifacts the runtime refuses — the R5 freshness-guard lesson, format
105
+ * edition. Also compared by the four hand-written base linkers (`neural-weights-{en-us,en-gb,en-nz,fr-fr}`), which
106
+ * import this constant rather than re-typing the number.
107
+ */
108
+ export declare const REQUIRED_PAIR_INDEX_SCHEMA = 3;
109
+ /**
110
+ * Warn when the per-locale FST a linker just symlinked was built from a DIFFERENT admin database than the one on disk
111
+ * now.
112
+ *
113
+ * WHY IT WARNS RATHER THAN REBUILDS, unlike its pair-index sibling above. A pair index is seconds of work and the
114
+ * linker owns its whole recipe. A locale FST is a multi-minute build whose output goes to a STAGING dir on purpose —
115
+ * the swap into `fst-per-locale/` is operator-gated after the battery, because an FST changes decoder behaviour and the
116
+ * D-rule does not let that land unmeasured. So the guard's job is to make the drift impossible to miss, and to name the
117
+ * command that starts fixing it. It is also why a stale FST is never fatal: the artifact is a decode-time bias list,
118
+ * and a dev tree must still run.
119
+ *
120
+ * The source-side half of the comparison lives here rather than in `fst-freshness.ts` for the same reason
121
+ * `pairIndexStaleReason` splits: only the caller knows which database it built against. All three FST-linking base
122
+ * packages build against the same one, so they share this rather than each pinning it.
123
+ */
124
+ export declare function warnIfFSTStale(fstPath: string, locale: string): void;
125
+ /**
126
+ * Build `pair-index-<country>.bin` into the overlay, skipping the work when the artifact on disk was already built at
127
+ * these magnitudes FROM the admin database on disk.
128
+ *
129
+ * The skip requires both halves (#1734): the header magnitudes (`pairIndexStaleReason`) AND the header's `sourceMD5s`
130
+ * against the current admin DB's md5. Magnitudes alone read a source change as "current" whenever pair counts happen
131
+ * not to move the calibrated numbers — the R5 freshness-guard lesson, which resurfaced in the 2026-08-18 admin swap
132
+ * when all four overlay locales skipped while the md5-checking base linkers rebuilt. This build's ONE source is the
133
+ * admin DB it passes as `--borough-db`, so the comparison is exactly one md5; a linker with a different source list
134
+ * (fr's BAN directory) owns its own guard and must never be pointed at this one.
135
+ *
136
+ * Exits non-zero on a failed build. Missing INPUTS (an unbuilt CLI, an absent WOF database) warn and return instead: a
137
+ * fresh clone has neither, and `yarn test` invokes this to verify auto-resolve, so a hard failure there would be a
138
+ * failure to have run a build yet rather than a real fault.
139
+ */
140
+ export declare function buildPairIndexOverlay({ packageDir, country, delta, transitionBeta, }: PairIndexOverlay): Promise<void>;
141
+ //# sourceMappingURL=weights-overlay-linker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weights-overlay-linker.d.ts","sourceRoot":"","sources":["../weights-overlay-linker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqBH;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CASzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAUlD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,GAAG,OAAO,CAY9G;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,aAAa,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,UAAU,EAAE,MAAM,EAAE,CAAA;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,CA2B7E;AAOD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBtE;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,qBAAqB,EAC7B,QAAQ,EAAE,oBAAoB,GAC5B,MAAM,GAAG,SAAS,CAgBpB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAA;AAE3C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAUpE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,qBAAqB,CAAC,EAC3C,UAAU,EACV,OAAO,EACP,KAAK,EACL,cAAc,GACd,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFlC"}
@@ -0,0 +1,259 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ * Shared development tooling for weights overlays: the symlink primitives every overlay linker uses, and the
6
+ * placetype-pair index build.
7
+ */
8
+ import { spawnSync } from "node:child_process";
9
+ import { existsSync, lstatSync, mkdirSync, readFileSync, renameSync, statSync, symlinkSync, unlinkSync, writeFileSync, } from "node:fs";
10
+ import { resolve } from "node:path";
11
+ import { parseJSONStrict } from "@mailwoman/core/objects";
12
+ import { dataRootPath, md5File, weightsOverlayPath, workspacePath } from "@mailwoman/core/utils";
13
+ import { fstFreshnessWarning } from "./fst-freshness.js";
14
+ /**
15
+ * Replicate `ln -sf SRC DEST` ATOMICALLY: symlink under a temp name, then rename over the destination. A plain
16
+ * unlink-then-symlink leaves a no-file window that concurrent vitest workers can hit mid-suite — bit CI on 2026-07-24.
17
+ * rename(2) replaces the destination atomically.
18
+ */
19
+ export function linkForce(src, dest) {
20
+ const tmp = `${dest}.tmp-link`;
21
+ if (existsSync(tmp)) {
22
+ unlinkSync(tmp);
23
+ }
24
+ symlinkSync(src, tmp);
25
+ renameSync(tmp, dest);
26
+ }
27
+ /**
28
+ * Remove a leftover local file/symlink so the #1179 base-weights fallback engages.
29
+ */
30
+ export function removeIfPresent(dest) {
31
+ try {
32
+ lstatSync(dest);
33
+ }
34
+ catch {
35
+ return;
36
+ }
37
+ unlinkSync(dest);
38
+ console.log(`removed stale local ${dest} (base fallback to en-us engages)`);
39
+ }
40
+ /**
41
+ * Symlink one soft-feed sibling into an overlay, warning rather than failing when the source is absent.
42
+ *
43
+ * Every one of these artifacts is OPTIONAL by design — the runtime has a fallback for each, so a fresh worktree that
44
+ * has not built the gazetteer still geocodes. That is why the miss prints the consequence instead of throwing: the
45
+ * operator needs to know which channel just resolved OFF, not to have the link step abort.
46
+ */
47
+ export function linkSoftFeedSibling(source, destination, consequenceIfMissing) {
48
+ if (!existsSync(source)) {
49
+ console.error(`WARNING: missing ${source} — ${consequenceIfMissing}`);
50
+ return false;
51
+ }
52
+ linkForce(source, destination);
53
+ console.log(`linked ${destination} \u2190 ${source}`);
54
+ return true;
55
+ }
56
+ /**
57
+ * Minimal PIX1 header reader — magic + header only, reimplemented so a data-only weights package gains no dependency on
58
+ * `@mailwoman/neural` (which pulls onnxruntime-node) to read a few fields. `neural/pair-index-resolver.ts`'s own header
59
+ * parse is the source of truth this must follow.
60
+ *
61
+ * Shared by the overlay build below AND by the four hand-written base linkers
62
+ * (`neural-weights-{en-us,en-gb,en-nz,fr-fr}/scripts/link-dev-weights.ts`), which each carried their own near-copy
63
+ * before 2026-08-04 — the ×5 clone the taste audit named, and the reason three of them were schema-blind while this one
64
+ * was not.
65
+ */
66
+ export function peekPairIndexHeaderFields(path) {
67
+ const bytes = readFileSync(path);
68
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
69
+ // "PIX1" little-endian.
70
+ const MAGIC = 0x31_58_49_50;
71
+ if (view.getUint32(0, true) !== MAGIC) {
72
+ throw new Error(`pair index: bad magic reading ${path}`);
73
+ }
74
+ const headerLen = view.getUint32(4, true);
75
+ const header = parseJSONStrict(Buffer.from(bytes.subarray(8, 8 + headerLen)).toString("utf8"));
76
+ return {
77
+ delta: header.delta,
78
+ transitionBeta: header.transitionBeta,
79
+ parentDelta: header.parentDelta,
80
+ schemaVersion: header.schemaVersion,
81
+ sourceMD5s: header.sourceMD5s ?? [],
82
+ };
83
+ }
84
+ /**
85
+ * Hex characters in an md5 digest.
86
+ */
87
+ const MD5_HEX_LENGTH = 32;
88
+ /**
89
+ * Md5 of `path`, cached in a standard `md5sum`-format sidecar (`<hash> <filename>`) beside it so a multi-gigabyte
90
+ * source is hashed once per change rather than once per linker run. The sidecar is trusted only when at least as new as
91
+ * the source; a missing or stale sidecar recomputes and rewrites, so the cache self-heals.
92
+ *
93
+ * The shared home for the copies the base linkers (`en-us`, `en-gb`, `en-nz`) each carry — new callers import this one.
94
+ */
95
+ export async function md5FileWithSidecar(path) {
96
+ const sidecarPath = `${path}.md5`;
97
+ const sourceStats = statSync(path);
98
+ if (existsSync(sidecarPath)) {
99
+ try {
100
+ if (statSync(sidecarPath).mtime >= sourceStats.mtime) {
101
+ const [hash] = readFileSync(sidecarPath, "utf8").trim().split(/\s+/);
102
+ if (hash && hash.length === MD5_HEX_LENGTH)
103
+ return hash;
104
+ }
105
+ }
106
+ catch {
107
+ // Unreadable sidecar — recompute below.
108
+ }
109
+ }
110
+ const hash = await md5File(path);
111
+ const filename = path.split(/[/\\]/).pop() || path;
112
+ writeFileSync(sidecarPath, `${hash} ${filename}\n`);
113
+ return hash;
114
+ }
115
+ /**
116
+ * Why an existing `pair-index-*.bin` is stale against `expected`, or `undefined` when its header matches. Covers the
117
+ * FORMAT (schemaVersion) and every calibrated magnitude; source-md5 freshness stays with the caller, because each base
118
+ * linker passes a different set of sources and only it knows what they are.
119
+ *
120
+ * One place so a magnitude added to the header cannot be checked by some linkers and not others — which is exactly how
121
+ * three of the four base linkers ended up unable to notice a schema bump.
122
+ */
123
+ export function pairIndexStaleReason(header, expected) {
124
+ if (header.schemaVersion !== REQUIRED_PAIR_INDEX_SCHEMA) {
125
+ return `schemaVersion ${header.schemaVersion} → ${REQUIRED_PAIR_INDEX_SCHEMA}`;
126
+ }
127
+ if (header.delta !== expected.delta)
128
+ return `delta ${header.delta} → ${expected.delta}`;
129
+ if (header.transitionBeta !== expected.transitionBeta) {
130
+ return `transitionBeta ${header.transitionBeta ?? "(absent)"} → ${expected.transitionBeta ?? "(absent)"}`;
131
+ }
132
+ if (header.parentDelta !== expected.parentDelta) {
133
+ return `parentDelta ${header.parentDelta ?? "(absent)"} → ${expected.parentDelta ?? "(absent)"}`;
134
+ }
135
+ return undefined;
136
+ }
137
+ /**
138
+ * The PIX1 schema this tree's reader requires. MUST equal `KNOWN_SCHEMA_VERSION` in `neural/pair-index-resolver.ts` —
139
+ * they are two ends of one fact, and this copy exists only because a data-only overlay must not gain a dependency on
140
+ * `@mailwoman/neural` (onnxruntime-node) to read one header field. Bump BOTH in the same commit; a schema bump that
141
+ * leaves this behind makes every dev checkout rebuild-loop or serve an artifact the runtime refuses.
142
+ *
143
+ * The freshness guard must compare it: a guard that checks only delta + source md5 reads a format-obsolete binary as
144
+ * "current" and leaves every dev checkout with artifacts the runtime refuses — the R5 freshness-guard lesson, format
145
+ * edition. Also compared by the four hand-written base linkers (`neural-weights-{en-us,en-gb,en-nz,fr-fr}`), which
146
+ * import this constant rather than re-typing the number.
147
+ */
148
+ export const REQUIRED_PAIR_INDEX_SCHEMA = 3;
149
+ /**
150
+ * Warn when the per-locale FST a linker just symlinked was built from a DIFFERENT admin database than the one on disk
151
+ * now.
152
+ *
153
+ * WHY IT WARNS RATHER THAN REBUILDS, unlike its pair-index sibling above. A pair index is seconds of work and the
154
+ * linker owns its whole recipe. A locale FST is a multi-minute build whose output goes to a STAGING dir on purpose —
155
+ * the swap into `fst-per-locale/` is operator-gated after the battery, because an FST changes decoder behaviour and the
156
+ * D-rule does not let that land unmeasured. So the guard's job is to make the drift impossible to miss, and to name the
157
+ * command that starts fixing it. It is also why a stale FST is never fatal: the artifact is a decode-time bias list,
158
+ * and a dev tree must still run.
159
+ *
160
+ * The source-side half of the comparison lives here rather than in `fst-freshness.ts` for the same reason
161
+ * `pairIndexStaleReason` splits: only the caller knows which database it built against. All three FST-linking base
162
+ * packages build against the same one, so they share this rather than each pinning it.
163
+ */
164
+ export function warnIfFSTStale(fstPath, locale) {
165
+ const warning = fstFreshnessWarning({
166
+ fstPath,
167
+ sourceDBPath: String(dataRootPath("wof", "admin-global-priority.db")),
168
+ rebuildCommand: `node packages/mailwoman/out/cli.js gazetteer build fst --locales ${locale} (writes to a staging dir; swap is operator-gated)`,
169
+ });
170
+ if (warning) {
171
+ console.error(warning);
172
+ }
173
+ }
174
+ /**
175
+ * Build `pair-index-<country>.bin` into the overlay, skipping the work when the artifact on disk was already built at
176
+ * these magnitudes FROM the admin database on disk.
177
+ *
178
+ * The skip requires both halves (#1734): the header magnitudes (`pairIndexStaleReason`) AND the header's `sourceMD5s`
179
+ * against the current admin DB's md5. Magnitudes alone read a source change as "current" whenever pair counts happen
180
+ * not to move the calibrated numbers — the R5 freshness-guard lesson, which resurfaced in the 2026-08-18 admin swap
181
+ * when all four overlay locales skipped while the md5-checking base linkers rebuilt. This build's ONE source is the
182
+ * admin DB it passes as `--borough-db`, so the comparison is exactly one md5; a linker with a different source list
183
+ * (fr's BAN directory) owns its own guard and must never be pointed at this one.
184
+ *
185
+ * Exits non-zero on a failed build. Missing INPUTS (an unbuilt CLI, an absent WOF database) warn and return instead: a
186
+ * fresh clone has neither, and `yarn test` invokes this to verify auto-resolve, so a hard failure there would be a
187
+ * failure to have run a build yet rather than a real fault.
188
+ */
189
+ export async function buildPairIndexOverlay({ packageDir, country, delta, transitionBeta, }) {
190
+ const CLI = String(workspacePath("mailwoman", "out", "cli.js"));
191
+ const ARTIFACT = `pair-index-${country}.bin`;
192
+ // Built into the data-root OVERLAY, not into the tracked package. The locale is recovered from the
193
+ // workspace name (`neural-weights-en-gb` → `en-gb`) so callers keep passing the one identifier they
194
+ // already had; the alternative was a second parameter every caller would have to keep in step with the
195
+ // first, which is the drift this whole rollout is removing.
196
+ const PKG_DIR = String(weightsOverlayPath(packageDir.replace(/^neural-weights-/, "")));
197
+ const DEST = resolve(PKG_DIR, ARTIFACT);
198
+ mkdirSync(PKG_DIR, { recursive: true });
199
+ /**
200
+ * Checked-in WOF-derived admin pairs — the same posture as the GB secondary sources.
201
+ */
202
+ const WOF_ADMIN_DB = String(dataRootPath("wof", "admin-global-priority.db"));
203
+ if (!existsSync(CLI)) {
204
+ console.error(`WARNING: ${CLI} not built — run \`yarn compile\` first, then re-run for ${ARTIFACT}.`);
205
+ return;
206
+ }
207
+ if (!existsSync(WOF_ADMIN_DB)) {
208
+ console.error(`WARNING: missing ${WOF_ADMIN_DB} — ${ARTIFACT} not built.`);
209
+ return;
210
+ }
211
+ if (existsSync(DEST)) {
212
+ try {
213
+ // No `parentDelta` in the expectation: the overlay locales (de/in/es/it) ship WITHOUT the whole-edge
214
+ // parent bias — unmeasured there, and the D-rule's answer to an unmeasured locale is a per-locale
215
+ // gate, not an inherited magnitude. `PairIndexOverlay` therefore has no `parentDelta` field to pass;
216
+ // adding one is a deliberate act that should arrive with a board.
217
+ const header = peekPairIndexHeaderFields(DEST);
218
+ const reason = pairIndexStaleReason(header, { delta, transitionBeta });
219
+ if (reason) {
220
+ console.log(`rebuilding ${ARTIFACT} — ${reason}`);
221
+ }
222
+ else {
223
+ // The source-md5 half (#1734). This build reads exactly one source, so one md5; an artifact that
224
+ // recorded none, or a different count, predates the stamp and is stale by that fact alone.
225
+ const adminMD5 = await md5FileWithSidecar(WOF_ADMIN_DB);
226
+ if (header.sourceMD5s.length === 1 && header.sourceMD5s[0] === adminMD5) {
227
+ console.log(`skipped ${ARTIFACT} build — ${DEST} is current (magnitudes + source md5 match)`);
228
+ return;
229
+ }
230
+ console.log(`rebuilding ${ARTIFACT} — header source md5s [${header.sourceMD5s.join(", ") || "(none recorded)"}] != ` +
231
+ `current admin DB [${adminMD5}]`);
232
+ }
233
+ }
234
+ catch (error) {
235
+ console.log(`rebuilding ${ARTIFACT} — header unreadable (${error.message})`);
236
+ }
237
+ }
238
+ const result = spawnSync(process.execPath, [
239
+ CLI,
240
+ "gazetteer",
241
+ "pair-index",
242
+ "--out",
243
+ PKG_DIR,
244
+ "--country",
245
+ country,
246
+ "--delta",
247
+ String(delta),
248
+ "--transition-beta",
249
+ String(transitionBeta),
250
+ "--borough-db",
251
+ WOF_ADMIN_DB,
252
+ ], { stdio: "inherit" });
253
+ if (result.status !== 0 || !existsSync(DEST)) {
254
+ console.error(`FAILED: gazetteer pair-index --country ${country} (exit ${result.status})`);
255
+ process.exit(1);
256
+ }
257
+ console.log(`built ${ARTIFACT} ← ${WOF_ADMIN_DB}`);
258
+ }
259
+ //# sourceMappingURL=weights-overlay-linker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weights-overlay-linker.js","sourceRoot":"","sources":["../weights-overlay-linker.ts"],"names":[],"mappings":"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"}