@mailwoman/registry 4.10.0 → 4.12.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.
- package/README.md +92 -0
- package/out/index.d.ts +2 -0
- package/out/index.d.ts.map +1 -1
- package/out/index.js +2 -0
- package/out/index.js.map +1 -1
- package/out/ingest.d.ts +12 -0
- package/out/ingest.d.ts.map +1 -1
- package/out/ingest.js +3 -3
- package/out/ingest.js.map +1 -1
- package/out/learned-scorer.d.ts +4 -2
- package/out/learned-scorer.d.ts.map +1 -1
- package/out/learned-scorer.js.map +1 -1
- package/out/map-html.d.ts +51 -0
- package/out/map-html.d.ts.map +1 -0
- package/out/map-html.js +262 -0
- package/out/map-html.js.map +1 -0
- package/out/reconcile.d.ts +86 -0
- package/out/reconcile.d.ts.map +1 -0
- package/out/reconcile.js +161 -0
- package/out/reconcile.js.map +1 -0
- package/out/resolve.d.ts +9 -9
- package/out/resolve.js +2 -2
- package/out/resolve.js.map +1 -1
- package/package.json +5 -4
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# @mailwoman/registry
|
|
2
|
+
|
|
3
|
+
**Geocode-first record-matching application** — the high-level entry point that
|
|
4
|
+
runs the full block → score → cluster pipeline over ingested records and returns
|
|
5
|
+
canonical entities ready for export.
|
|
6
|
+
|
|
7
|
+
This is the clinic-funding use case Mailwoman was built for, standing on a
|
|
8
|
+
calibrated, label-free matcher.
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { resolveEntities, ingestRows, toGeoJSON } from "@mailwoman/registry";
|
|
12
|
+
|
|
13
|
+
// 1. Ingest — CSV/array → normalized SourceRecords
|
|
14
|
+
const records = ingestRows(rows, {
|
|
15
|
+
mapping: { name: "Provider Name", address: "Street Address", city: "City", ... },
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// 2. Resolve — block → score → cluster with geo-first defaults
|
|
19
|
+
const entities = resolveEntities(records, {
|
|
20
|
+
geocodeAddress: async (row) => ({ lat: 30.2672, lon: -97.7431 }),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// 3. Export — GeoJSON for QGIS
|
|
24
|
+
const fc = toGeoJSON(entities);
|
|
25
|
+
// → FeatureCollection with Point features + entity properties
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## The full pipeline
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
CSV / SQLite → ingestRows → SourceRecord[] → resolveEntities → ResolvedEntity[]
|
|
32
|
+
↓
|
|
33
|
+
toGeoJSON()
|
|
34
|
+
↓
|
|
35
|
+
GeoJSON → QGIS
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
// Ingest — parse CSV / map columns → normalized records
|
|
42
|
+
import { ingestRows, parseCsv, inferMapping } from "@mailwoman/registry"
|
|
43
|
+
// {
|
|
44
|
+
// ingestRows(rows, opts): SourceRecord[]
|
|
45
|
+
// parseCsv(csvText): string[][]
|
|
46
|
+
// inferMapping(headers): ColumnMapping
|
|
47
|
+
// }
|
|
48
|
+
|
|
49
|
+
// Resolve — run the full matcher pipeline
|
|
50
|
+
import { resolveEntities } from "@mailwoman/registry"
|
|
51
|
+
// resolveEntities(records, config): ResolvedEntity[]
|
|
52
|
+
// Config: { geocodeAddress?, scorer?, blockingKeys?, threshold?, discriminators? }
|
|
53
|
+
|
|
54
|
+
// Export — GeoJSON, MapLibre HTML, reconciliation reports
|
|
55
|
+
import { toGeoJSON, toMapHTML, reconcile } from "@mailwoman/registry"
|
|
56
|
+
|
|
57
|
+
// Learned scorer — pre-trained GBT for single-dataset dedup
|
|
58
|
+
import { dedupGbtEnUs } from "@mailwoman/registry"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Default configuration
|
|
62
|
+
|
|
63
|
+
`resolveEntities` ships with sensible defaults:
|
|
64
|
+
|
|
65
|
+
- **Blocking keys:** geo-cell (H3) + canonical address + phone + email
|
|
66
|
+
- **Scoring model:** Fellegi-Sunter with label-free EM, term frequency adjustment
|
|
67
|
+
- **Learned scorer:** optional GBT for single-dataset dedup (opt-in via `scorer`)
|
|
68
|
+
- **Threshold:** 0.5 (configurable precision/recall knob)
|
|
69
|
+
|
|
70
|
+
## CLI
|
|
71
|
+
|
|
72
|
+
The `mailwoman` CLI exposes `registry` as a command:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Multi-source entity resolution
|
|
76
|
+
mailwoman registry --sources config.json --out entities.geojson
|
|
77
|
+
|
|
78
|
+
# Cross-dataset reconciliation
|
|
79
|
+
mailwoman registry --sources tx-nppes.json --reconcile tx-fcc.json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Related
|
|
83
|
+
|
|
84
|
+
- [`@mailwoman/match`](../match) — the low-level block/score/cluster primitives
|
|
85
|
+
- [`@mailwoman/record`](../record) — `SourceRecord` schema and normalizers
|
|
86
|
+
- [`@mailwoman/address-id`](../address-id) — exact-match join key
|
|
87
|
+
- [Geocode-First Record Matching](https://mailwoman.sister.software/articles/concepts/geocode-first-record-matching/)
|
|
88
|
+
- [Dedup Entity Truth](https://mailwoman.sister.software/articles/concepts/dedup-entity-truth/)
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
[AGPL-3.0-only](https://www.gnu.org/licenses/agpl-3.0.html)
|
package/out/index.d.ts
CHANGED
|
@@ -14,7 +14,9 @@ export * from "./address-key.js";
|
|
|
14
14
|
export * from "./geojson.js";
|
|
15
15
|
export * from "./ingest.js";
|
|
16
16
|
export * from "./learned-scorer.js";
|
|
17
|
+
export * from "./map-html.js";
|
|
17
18
|
export * from "./models/dedup-gbt-en-us.js";
|
|
19
|
+
export * from "./reconcile.js";
|
|
18
20
|
export * from "./resolve.js";
|
|
19
21
|
export * from "./types.js";
|
|
20
22
|
//# sourceMappingURL=index.d.ts.map
|
package/out/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA;AAC7B,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA"}
|
package/out/index.js
CHANGED
|
@@ -14,7 +14,9 @@ export * from "./address-key.js";
|
|
|
14
14
|
export * from "./geojson.js";
|
|
15
15
|
export * from "./ingest.js";
|
|
16
16
|
export * from "./learned-scorer.js";
|
|
17
|
+
export * from "./map-html.js";
|
|
17
18
|
export * from "./models/dedup-gbt-en-us.js";
|
|
19
|
+
export * from "./reconcile.js";
|
|
18
20
|
export * from "./resolve.js";
|
|
19
21
|
export * from "./types.js";
|
|
20
22
|
//# sourceMappingURL=index.js.map
|
package/out/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA;AAC7B,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA"}
|
package/out/ingest.d.ts
CHANGED
|
@@ -88,6 +88,18 @@ export declare function inferMapping(header: readonly string[]): ColumnMapping;
|
|
|
88
88
|
export interface IngestOptions {
|
|
89
89
|
/** The geocoding seam. Without it, records carry name/org but no resolved address. */
|
|
90
90
|
geocodeAddress?: GeocodeAddress;
|
|
91
|
+
/**
|
|
92
|
+
* Separator for joining a multi-column ADDRESS mapping (name/org always join with a space).
|
|
93
|
+
* Default `" "`. Pass `", "` to give the parser delimited input (`"214 Main St, Austin, TX
|
|
94
|
+
* 78701"`) instead of a concatenated run (`"214 Main St Austin TX 78701"`) — the latter strips
|
|
95
|
+
* the parser's segmentation boundaries and is partly OOD (it also breaks all-caps
|
|
96
|
+
* case-normalization; #694). **Default `", "` (#694 flip, validated).** Comma-join is the correct
|
|
97
|
+
* shape for an address built from separate columns, and #700 measured it at +15% cross-dataset
|
|
98
|
+
* rooftop (579→667) with no comma-less crater. The dedup GBT was trained on the old space-joined
|
|
99
|
+
* coords, so this flip is paired with a GBT re-validation (#694). Pass `" "` to restore the
|
|
100
|
+
* legacy space-join for a byte-stable A/B.
|
|
101
|
+
*/
|
|
102
|
+
addressSeparator?: string;
|
|
91
103
|
}
|
|
92
104
|
/** Parse a CSV string (with a header row) into row objects keyed by column name. */
|
|
93
105
|
export declare function parseCsv(text: string): Record<string, string>[];
|
package/out/ingest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../ingest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAiD,eAAe,EAAe,MAAM,mBAAmB,CAAA;AAI/G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,mGAAmG;AACnG,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,aAAa,GAAG,IAAI,CAAA;AAElG,8CAA8C;AAC9C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,KAAK,CAAA;AAEvC,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAEpD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAuB,UAAU,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,SAAS,CAAA;CAAO,GAClC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA0BxC;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC7B,mEAAmE;IACnE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;CAC9C;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,aAAa,CA4CrE;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC7B,sFAAsF;IACtF,cAAc,CAAC,EAAE,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../ingest.ts"],"names":[],"mappings":"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"}
|
package/out/ingest.js
CHANGED
|
@@ -124,14 +124,14 @@ export function parseCsv(text) {
|
|
|
124
124
|
return parseCsvSync(text, { columns: true, skip_empty_lines: true, trim: true, relax_column_count: true });
|
|
125
125
|
}
|
|
126
126
|
/** Join the named column(s) of a row into a single trimmed string, or undefined if empty. */
|
|
127
|
-
function pick(row, columns) {
|
|
127
|
+
function pick(row, columns, separator = " ") {
|
|
128
128
|
if (!columns)
|
|
129
129
|
return undefined;
|
|
130
130
|
const list = Array.isArray(columns) ? columns : [columns];
|
|
131
131
|
const value = list
|
|
132
132
|
.map((c) => row[c]?.trim())
|
|
133
133
|
.filter(Boolean)
|
|
134
|
-
.join(
|
|
134
|
+
.join(separator)
|
|
135
135
|
.trim();
|
|
136
136
|
return value || undefined;
|
|
137
137
|
}
|
|
@@ -147,7 +147,7 @@ export async function ingestRows(rows, mapping, opts = {}) {
|
|
|
147
147
|
const id = (mapping.id ? row[mapping.id]?.trim() : "") || String(index);
|
|
148
148
|
const nameValue = pick(row, mapping.name);
|
|
149
149
|
const orgValue = pick(row, mapping.organization);
|
|
150
|
-
const addressValue = pick(row, mapping.address);
|
|
150
|
+
const addressValue = pick(row, mapping.address, opts.addressSeparator ?? ", ");
|
|
151
151
|
let attributes;
|
|
152
152
|
if (mapping.attributes) {
|
|
153
153
|
for (const [key, columns] of Object.entries(mapping.attributes)) {
|
package/out/ingest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../ingest.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../ingest.ts"],"names":[],"mappings":"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"}
|
package/out/learned-scorer.d.ts
CHANGED
|
@@ -33,8 +33,10 @@ export interface LearnedFeatureConfig {
|
|
|
33
33
|
* FS weight wholesale and owns its own feature vector.)
|
|
34
34
|
*/
|
|
35
35
|
comparisons: Comparison<SourceRecord>[];
|
|
36
|
-
/**
|
|
37
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Address-frequency table for the crowdedness feature (a crowded shared address is weak
|
|
38
|
+
* identity).
|
|
39
|
+
*/
|
|
38
40
|
addressFrequency: TermFrequencyTable;
|
|
39
41
|
}
|
|
40
42
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learned-scorer.d.ts","sourceRoot":"","sources":["../learned-scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAoB,KAAK,UAAU,EAAE,KAAK,GAAG,EAAY,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACjH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,4DAA4D;AAC5D,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,WAAW,EAAE,UAAU,CAAC,YAAY,CAAC,EAAE,CAAA;IACvC;
|
|
1
|
+
{"version":3,"file":"learned-scorer.d.ts","sourceRoot":"","sources":["../learned-scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAoB,KAAK,UAAU,EAAE,KAAK,GAAG,EAAY,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACjH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,4DAA4D;AAC5D,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,WAAW,EAAE,UAAU,CAAC,YAAY,CAAC,EAAE,CAAA;IACvC;;;OAGG;IACH,gBAAgB,EAAE,kBAAkB,CAAA;CACpC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,GAAG,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,KAAK,MAAM,EAAE,CAkClH;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC9B,MAAM,EAAE,oBAAoB,GAAG;IAAE,KAAK,EAAE,GAAG,CAAA;CAAE,GAC3C,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,KAAK,MAAM,CAI9C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learned-scorer.js","sourceRoot":"","sources":["../learned-scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,gBAAgB,EAA6B,QAAQ,EAA2B,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"learned-scorer.js","sourceRoot":"","sources":["../learned-scorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Render resolved entities as a standalone map page — the visual complement to {@link toGeoJSON}'s
|
|
7
|
+
* QGIS/analyst export. `toMapHTML(featureCollection)` returns one HTML file you open in a
|
|
8
|
+
* browser; no server, no build.
|
|
9
|
+
*
|
|
10
|
+
* It renders on the HOUSE stack: MapLibre GL + a Protomaps basemap (`@protomaps/basemaps` generates
|
|
11
|
+
* the `layers()` for a named flavor) over the `basemap-v4` vector tiles served from R2 at
|
|
12
|
+
* `tiles.sister.software` — the same basemap the demo uses. Each entity is a circle sized by
|
|
13
|
+
* records-merged and colored by cross-dataset-link status (≥2 sources stand out), or
|
|
14
|
+
* categorically by `bucket` when the reconciliation output carries one. Pure: GeoJSON in, HTML
|
|
15
|
+
* string out (the Protomaps layer specs are generated at this point and inlined). The generated
|
|
16
|
+
* page fetches MapLibre, the basemap tiles, and glyphs/sprite over the network when opened (the
|
|
17
|
+
* house infra).
|
|
18
|
+
*
|
|
19
|
+
* SERVE IT OVER LOCALHOST, don't open it as a file. The house tile server (`tiles.sister.software`)
|
|
20
|
+
* CORS-restricts to localhost + the docs domains, so a `file://` page shows the (accurate)
|
|
21
|
+
* markers on a blank basemap. `npx serve` / `python3 -m http.server` in the output directory is
|
|
22
|
+
* enough; the page also surfaces a hint banner when it detects it's running from `file://`.
|
|
23
|
+
*
|
|
24
|
+
* Neutral entity-resolution view: it shows what resolved to what and how confidently (cohesion).
|
|
25
|
+
* Bucket labels render verbatim from the data, never editorialized.
|
|
26
|
+
*/
|
|
27
|
+
import type { GeoJsonFeatureCollection } from "./types.js";
|
|
28
|
+
/** Protomaps stock flavors (shipped by `@protomaps/basemaps`). */
|
|
29
|
+
export type MapFlavor = "light" | "dark" | "white" | "grayscale" | "black";
|
|
30
|
+
export interface MapHTMLOptions {
|
|
31
|
+
/** Document `<title>` + on-map heading. Default: "Mailwoman — resolved entities". */
|
|
32
|
+
title?: string;
|
|
33
|
+
/** Protomaps basemap flavor. Default: "light" (data points read cleanly over it). */
|
|
34
|
+
flavor?: MapFlavor;
|
|
35
|
+
/**
|
|
36
|
+
* How to color the markers:
|
|
37
|
+
*
|
|
38
|
+
* - `"auto"` (default) — by `bucket` if any feature carries one (reconciliation output), else by
|
|
39
|
+
* cross-dataset-link status.
|
|
40
|
+
* - `"sources"` — always by cross-dataset-link status (≥2 sources stand out).
|
|
41
|
+
* - `"bucket"` — always by the `bucket` property.
|
|
42
|
+
*/
|
|
43
|
+
colorBy?: "auto" | "sources" | "bucket";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Render `geojson` (a {@link toGeoJSON} / reconciliation FeatureCollection) as a complete,
|
|
47
|
+
* standalone HTML document. Entities without a coordinate are already absent from those
|
|
48
|
+
* collections; an empty collection renders a friendly empty state rather than a broken map.
|
|
49
|
+
*/
|
|
50
|
+
export declare function toMapHTML(geojson: GeoJsonFeatureCollection, options?: MapHTMLOptions): string;
|
|
51
|
+
//# sourceMappingURL=map-html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-html.d.ts","sourceRoot":"","sources":["../map-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAuB1D,kEAAkE;AAClE,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CAAA;AAE1E,MAAM,WAAW,cAAc;IAC9B,qFAAqF;IACrF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qFAAqF;IACrF,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAA;CACvC;AAyBD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,wBAAwB,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,CAmMjG"}
|
package/out/map-html.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Render resolved entities as a standalone map page — the visual complement to {@link toGeoJSON}'s
|
|
7
|
+
* QGIS/analyst export. `toMapHTML(featureCollection)` returns one HTML file you open in a
|
|
8
|
+
* browser; no server, no build.
|
|
9
|
+
*
|
|
10
|
+
* It renders on the HOUSE stack: MapLibre GL + a Protomaps basemap (`@protomaps/basemaps` generates
|
|
11
|
+
* the `layers()` for a named flavor) over the `basemap-v4` vector tiles served from R2 at
|
|
12
|
+
* `tiles.sister.software` — the same basemap the demo uses. Each entity is a circle sized by
|
|
13
|
+
* records-merged and colored by cross-dataset-link status (≥2 sources stand out), or
|
|
14
|
+
* categorically by `bucket` when the reconciliation output carries one. Pure: GeoJSON in, HTML
|
|
15
|
+
* string out (the Protomaps layer specs are generated at this point and inlined). The generated
|
|
16
|
+
* page fetches MapLibre, the basemap tiles, and glyphs/sprite over the network when opened (the
|
|
17
|
+
* house infra).
|
|
18
|
+
*
|
|
19
|
+
* SERVE IT OVER LOCALHOST, don't open it as a file. The house tile server (`tiles.sister.software`)
|
|
20
|
+
* CORS-restricts to localhost + the docs domains, so a `file://` page shows the (accurate)
|
|
21
|
+
* markers on a blank basemap. `npx serve` / `python3 -m http.server` in the output directory is
|
|
22
|
+
* enough; the page also surfaces a hint banner when it detects it's running from `file://`.
|
|
23
|
+
*
|
|
24
|
+
* Neutral entity-resolution view: it shows what resolved to what and how confidently (cohesion).
|
|
25
|
+
* Bucket labels render verbatim from the data, never editorialized.
|
|
26
|
+
*/
|
|
27
|
+
import { layers, namedFlavor } from "@protomaps/basemaps";
|
|
28
|
+
/** MapLibre GL release the page pins (CDN + SRI). Matches the workspace's `maplibre-gl` major. */
|
|
29
|
+
const MAPLIBRE_VERSION = "5.24.0";
|
|
30
|
+
const MAPLIBRE_JS_SRI = "sha384-5+cfbwT0iiub6VsQAdn6yz16nr6sDiQoHx6tm4O8OVYXHYOxcffFmCJBL0dgdvGp";
|
|
31
|
+
const MAPLIBRE_CSS_SRI = "sha384-uTttxo/aOKbdE5RlD/SPzSDoDmNvGlUYPjONi2MN/b7c9HPSvW07OIuyP7uL6jxK";
|
|
32
|
+
/**
|
|
33
|
+
* The house Protomaps basemap: `basemap-v4` PMTiles (tile-worker → R2 at `tiles.sister.software`,
|
|
34
|
+
* which sends CORS for localhost + the docs domains).
|
|
35
|
+
*
|
|
36
|
+
* Glyphs + sprite come from the UPSTREAM Protomaps assets (GitHub Pages, `ACAO: *`), not the house
|
|
37
|
+
* mirror at `public.sister.software` — that bucket sends no CORS headers, so the mirror can't be
|
|
38
|
+
* fetched cross-origin (`cartographer/base/composition.ts` flags the same: "Currently upstream
|
|
39
|
+
* URLs; we mirror these … but no public route fronts that bucket yet"). The upstream assets target
|
|
40
|
+
* the v4 schema, matching the `basemap-v4` tiles. Swap to the house mirror once it has a
|
|
41
|
+
* CORS-enabled route.
|
|
42
|
+
*/
|
|
43
|
+
const BASEMAP_SOURCE_ID = "basemap-v4";
|
|
44
|
+
const BASEMAP_TILEJSON_URL = "https://tiles.sister.software/basemap-v4.json";
|
|
45
|
+
const GLYPHS_URL = "https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf";
|
|
46
|
+
const SPRITE_URL = "https://protomaps.github.io/basemaps-assets/sprites/v4/light";
|
|
47
|
+
/** Categorical palette (reused for buckets; cycles if there are more buckets than entries). */
|
|
48
|
+
const PALETTE = ["#2f9e44", "#f08c00", "#1971c2", "#e8590c", "#9c36b5", "#0c8599", "#e03131", "#5c940d"];
|
|
49
|
+
const SINGLE_COLOR = "#3388ff"; // single-source entity
|
|
50
|
+
const CROSS_COLOR = "#e8590c"; // cross-dataset link (≥2 sources)
|
|
51
|
+
/**
|
|
52
|
+
* Escape a value for safe inlining inside a `<script>` as JSON. `JSON.stringify` alone isn't enough
|
|
53
|
+
* — a record value containing `</script>` would close the block early; escaping `<`/`>`/`&` to
|
|
54
|
+
* `\uXXXX` keeps the JSON valid and makes a breakout impossible.
|
|
55
|
+
*/
|
|
56
|
+
function safeJsonForScript(value) {
|
|
57
|
+
return JSON.stringify(value).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
|
|
58
|
+
}
|
|
59
|
+
/** Escape text for the HTML document body (title/heading), not the inlined script. */
|
|
60
|
+
function escapeHtml(text) {
|
|
61
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
62
|
+
}
|
|
63
|
+
function sourceCount(props) {
|
|
64
|
+
return Array.isArray(props["sources"]) ? props["sources"].length : 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Render `geojson` (a {@link toGeoJSON} / reconciliation FeatureCollection) as a complete,
|
|
68
|
+
* standalone HTML document. Entities without a coordinate are already absent from those
|
|
69
|
+
* collections; an empty collection renders a friendly empty state rather than a broken map.
|
|
70
|
+
*/
|
|
71
|
+
export function toMapHTML(geojson, options = {}) {
|
|
72
|
+
const title = options.title ?? "Mailwoman — resolved entities";
|
|
73
|
+
const flavorName = options.flavor ?? "light";
|
|
74
|
+
const colorBy = options.colorBy ?? "auto";
|
|
75
|
+
const hasBuckets = geojson.features.some((f) => f.properties?.["bucket"] != null);
|
|
76
|
+
const mode = colorBy === "auto" ? (hasBuckets ? "bucket" : "sources") : colorBy;
|
|
77
|
+
// Assign a color to each distinct bucket value, in first-seen order.
|
|
78
|
+
const bucketColors = {};
|
|
79
|
+
if (mode === "bucket") {
|
|
80
|
+
let i = 0;
|
|
81
|
+
for (const f of geojson.features) {
|
|
82
|
+
const b = f.properties?.["bucket"] != null ? String(f.properties["bucket"]) : "—";
|
|
83
|
+
if (!(b in bucketColors))
|
|
84
|
+
bucketColors[b] = PALETTE[i++ % PALETTE.length];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const colorFor = (props) => {
|
|
88
|
+
if (mode === "bucket") {
|
|
89
|
+
const b = props["bucket"] != null ? String(props["bucket"]) : "—";
|
|
90
|
+
return bucketColors[b] ?? SINGLE_COLOR;
|
|
91
|
+
}
|
|
92
|
+
return sourceCount(props) >= 2 ? CROSS_COLOR : SINGLE_COLOR;
|
|
93
|
+
};
|
|
94
|
+
// Precompute the per-feature color (`_color`) so the circle layer is a simple `["get","_color"]`,
|
|
95
|
+
// and the bounding box, both at generate time. The data is copied (not mutated in place).
|
|
96
|
+
let minLng = Infinity;
|
|
97
|
+
let minLat = Infinity;
|
|
98
|
+
let maxLng = -Infinity;
|
|
99
|
+
let maxLat = -Infinity;
|
|
100
|
+
const features = geojson.features.map((f) => {
|
|
101
|
+
const [lng, lat] = f.geometry.coordinates;
|
|
102
|
+
if (lng < minLng)
|
|
103
|
+
minLng = lng;
|
|
104
|
+
if (lat < minLat)
|
|
105
|
+
minLat = lat;
|
|
106
|
+
if (lng > maxLng)
|
|
107
|
+
maxLng = lng;
|
|
108
|
+
if (lat > maxLat)
|
|
109
|
+
maxLat = lat;
|
|
110
|
+
return { ...f, properties: { ...f.properties, _color: colorFor(f.properties) } };
|
|
111
|
+
});
|
|
112
|
+
const bbox = features.length ? [[minLng, minLat], [maxLng, maxLat]] : null;
|
|
113
|
+
// The full MapLibre style: the Protomaps basemap layers (generated here) over the house basemap-v4
|
|
114
|
+
// vector source, plus our inlined entities source + a circle layer keyed off the precomputed color.
|
|
115
|
+
const style = {
|
|
116
|
+
version: 8,
|
|
117
|
+
glyphs: GLYPHS_URL,
|
|
118
|
+
sprite: SPRITE_URL,
|
|
119
|
+
sources: {
|
|
120
|
+
[BASEMAP_SOURCE_ID]: { type: "vector", url: BASEMAP_TILEJSON_URL },
|
|
121
|
+
entities: { type: "geojson", data: { type: "FeatureCollection", features } },
|
|
122
|
+
},
|
|
123
|
+
layers: [
|
|
124
|
+
...layers(BASEMAP_SOURCE_ID, namedFlavor(flavorName), { lang: "en" }),
|
|
125
|
+
{
|
|
126
|
+
id: "mw-entities",
|
|
127
|
+
type: "circle",
|
|
128
|
+
source: "entities",
|
|
129
|
+
paint: {
|
|
130
|
+
"circle-radius": [
|
|
131
|
+
"interpolate",
|
|
132
|
+
["linear"],
|
|
133
|
+
["coalesce", ["get", "recordCount"], 1],
|
|
134
|
+
1,
|
|
135
|
+
5,
|
|
136
|
+
5,
|
|
137
|
+
9,
|
|
138
|
+
25,
|
|
139
|
+
15,
|
|
140
|
+
100,
|
|
141
|
+
22,
|
|
142
|
+
],
|
|
143
|
+
"circle-color": ["get", "_color"],
|
|
144
|
+
"circle-stroke-color": "#ffffff",
|
|
145
|
+
"circle-stroke-width": 1.2,
|
|
146
|
+
"circle-opacity": 0.9,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
};
|
|
151
|
+
// Legend rows, built here so arbitrary bucket sets render without client-side guessing.
|
|
152
|
+
const legendRows = mode === "bucket"
|
|
153
|
+
? Object.entries(bucketColors)
|
|
154
|
+
.map(([b, c]) => `<div><i style="background:${c}"></i>${escapeHtml(b)}</div>`)
|
|
155
|
+
.join("")
|
|
156
|
+
: `<div><i style="background:${CROSS_COLOR}"></i>cross-dataset link (≥2 sources)</div>` +
|
|
157
|
+
`<div><i style="background:${SINGLE_COLOR}"></i>single-source entity</div>` +
|
|
158
|
+
`<div class="muted" style="margin-top:4px">marker size = records merged</div>`;
|
|
159
|
+
const crossLinks = geojson.features.filter((f) => sourceCount(f.properties) >= 2).length;
|
|
160
|
+
const summary = `${geojson.features.length} entities` + (mode === "sources" ? ` · ${crossLinks} cross-dataset links` : "");
|
|
161
|
+
// The client script avoids template literals and `${` so it survives this outer template verbatim.
|
|
162
|
+
return `<!doctype html>
|
|
163
|
+
<html lang="en">
|
|
164
|
+
<head>
|
|
165
|
+
<meta charset="utf-8" />
|
|
166
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
167
|
+
<title>${escapeHtml(title)}</title>
|
|
168
|
+
<link
|
|
169
|
+
rel="stylesheet"
|
|
170
|
+
href="https://unpkg.com/maplibre-gl@${MAPLIBRE_VERSION}/dist/maplibre-gl.css"
|
|
171
|
+
integrity="${MAPLIBRE_CSS_SRI}"
|
|
172
|
+
crossorigin="anonymous" />
|
|
173
|
+
<style>
|
|
174
|
+
html, body { margin: 0; height: 100%; font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }
|
|
175
|
+
#map { position: absolute; inset: 0; }
|
|
176
|
+
.mw-panel {
|
|
177
|
+
position: absolute; z-index: 1; background: rgba(255,255,255,0.94); padding: 10px 12px;
|
|
178
|
+
border-radius: 8px; box-shadow: 0 1px 6px rgba(0,0,0,0.3); font-size: 12px; line-height: 1.5; color: #1a1a1a;
|
|
179
|
+
}
|
|
180
|
+
.mw-title { top: 10px; left: 10px; max-width: 60%; }
|
|
181
|
+
.mw-title h1 { font-size: 14px; margin: 0 0 4px; }
|
|
182
|
+
.mw-legend { bottom: 22px; right: 10px; }
|
|
183
|
+
.mw-legend i { display: inline-block; width: 12px; height: 12px; margin-right: 6px; border-radius: 50%; vertical-align: -1px; }
|
|
184
|
+
.muted { color: #666; }
|
|
185
|
+
.mw-popup { font-size: 12px; line-height: 1.5; max-width: 260px; }
|
|
186
|
+
.mw-popup .nm { font-weight: 600; font-size: 13px; }
|
|
187
|
+
.mw-popup dt { color: #666; display: inline; }
|
|
188
|
+
.mw-popup .link { color: ${CROSS_COLOR}; font-weight: 600; }
|
|
189
|
+
.mw-empty { position: absolute; inset: 0; display: grid; place-items: center; z-index: 1; }
|
|
190
|
+
.mw-warn { bottom: 10px; left: 10px; max-width: 52%; background: rgba(255,243,205,0.97); }
|
|
191
|
+
.mw-warn code { background: rgba(0,0,0,0.06); padding: 0 3px; border-radius: 3px; }
|
|
192
|
+
</style>
|
|
193
|
+
</head>
|
|
194
|
+
<body>
|
|
195
|
+
<div id="map"></div>
|
|
196
|
+
<div class="mw-panel mw-title"><h1>${escapeHtml(title)}</h1><div class="muted">${summary}</div></div>
|
|
197
|
+
${features.length ? `<div class="mw-panel mw-legend">${legendRows}</div>` : `<div class="mw-empty"><div class="mw-panel"><h1>${escapeHtml(title)}</h1><div class="muted">No geocoded entities to display.</div></div></div>`}
|
|
198
|
+
<script
|
|
199
|
+
src="https://unpkg.com/maplibre-gl@${MAPLIBRE_VERSION}/dist/maplibre-gl.js"
|
|
200
|
+
integrity="${MAPLIBRE_JS_SRI}"
|
|
201
|
+
crossorigin="anonymous"></script>
|
|
202
|
+
<script>
|
|
203
|
+
"use strict";
|
|
204
|
+
var STYLE = ${safeJsonForScript(style)};
|
|
205
|
+
var BBOX = ${safeJsonForScript(bbox)};
|
|
206
|
+
|
|
207
|
+
function esc(v) {
|
|
208
|
+
if (v === null || v === undefined) return "";
|
|
209
|
+
return String(v).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function popupHtml(p) {
|
|
213
|
+
var rows = [];
|
|
214
|
+
var heading = p.name || p.organization || p.entityId || "entity";
|
|
215
|
+
rows.push('<div class="nm">' + esc(heading) + '</div>');
|
|
216
|
+
if (p.organization && p.organization !== p.name) rows.push('<div>' + esc(p.organization) + '</div>');
|
|
217
|
+
if (p.address) rows.push('<div class="muted">' + esc(p.address) + '</div>');
|
|
218
|
+
rows.push('<hr style="border:none;border-top:1px solid #eee;margin:6px 0" />');
|
|
219
|
+
rows.push('<div><dt>records merged:</dt> ' + esc(p.recordCount) + '</div>');
|
|
220
|
+
var srcs = Array.isArray(p.sources) ? p.sources : [];
|
|
221
|
+
if (srcs.length) {
|
|
222
|
+
var cls = srcs.length >= 2 ? ' class="link"' : '';
|
|
223
|
+
rows.push('<div><dt>sources:</dt> <span' + cls + '>' + esc(srcs.join(", ")) + '</span>'
|
|
224
|
+
+ (srcs.length >= 2 ? ' (cross-dataset link)' : '') + '</div>');
|
|
225
|
+
}
|
|
226
|
+
if (p.bucket !== null && p.bucket !== undefined) rows.push('<div><dt>bucket:</dt> ' + esc(p.bucket) + '</div>');
|
|
227
|
+
if (p.cohesion !== null && p.cohesion !== undefined) rows.push('<div><dt>cohesion:</dt> ' + esc(p.cohesion) + ' bits</div>');
|
|
228
|
+
if (p.geocodeTier) rows.push('<div><dt>geocode tier:</dt> ' + esc(p.geocodeTier) + '</div>');
|
|
229
|
+
return '<div class="mw-popup">' + rows.join("") + '</div>';
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
var map = new maplibregl.Map({ container: "map", style: STYLE, center: [-98, 39], zoom: 3, attributionControl: { compact: true } });
|
|
233
|
+
map.addControl(new maplibregl.NavigationControl({ showCompass: false }), "top-right");
|
|
234
|
+
|
|
235
|
+
map.on("load", function () {
|
|
236
|
+
if (BBOX) map.fitBounds(BBOX, { padding: 56, maxZoom: 15, duration: 0 });
|
|
237
|
+
});
|
|
238
|
+
map.on("click", "mw-entities", function (e) {
|
|
239
|
+
var f = e.features && e.features[0];
|
|
240
|
+
if (!f) return;
|
|
241
|
+
new maplibregl.Popup({ closeButton: true }).setLngLat(e.lngLat).setHTML(popupHtml(f.properties || {})).addTo(map);
|
|
242
|
+
});
|
|
243
|
+
map.on("mouseenter", "mw-entities", function () { map.getCanvas().style.cursor = "pointer"; });
|
|
244
|
+
map.on("mouseleave", "mw-entities", function () { map.getCanvas().style.cursor = ""; });
|
|
245
|
+
|
|
246
|
+
// The house basemap tiles are CORS-restricted to localhost + the docs domain, so a page opened
|
|
247
|
+
// straight off disk (file://) shows the markers on a blank basemap. Make that explicit rather than
|
|
248
|
+
// silent — the entity positions are correct regardless of whether the basemap paints.
|
|
249
|
+
if (location.protocol === "file:") {
|
|
250
|
+
var warn = document.createElement("div");
|
|
251
|
+
warn.className = "mw-panel mw-warn";
|
|
252
|
+
warn.innerHTML = "⚠ Basemap tiles are blocked from <code>file://</code>. Serve this over "
|
|
253
|
+
+ "<code>http://localhost</code> (e.g. <code>npx serve</code> or <code>python3 -m http.server</code>) "
|
|
254
|
+
+ "to see the map background — the markers are accurate either way.";
|
|
255
|
+
document.body.appendChild(warn);
|
|
256
|
+
}
|
|
257
|
+
</script>
|
|
258
|
+
</body>
|
|
259
|
+
</html>
|
|
260
|
+
`;
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=map-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-html.js","sourceRoot":"","sources":["../map-html.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Coverage reconciliation (#621) — the library home for what `scripts/record-matcher/
|
|
7
|
+
* coverage-reconciliation.ts` does inline, so the CLI (`registry --reconcile`) and any consumer
|
|
8
|
+
* can reuse it.
|
|
9
|
+
*
|
|
10
|
+
* Given entities already resolved ACROSS sources (#618), classify each by which KIND of source its
|
|
11
|
+
* records come from. You tag each source label as either an **eligibility** source (it denotes
|
|
12
|
+
* membership in some base set — e.g. registered providers/facilities) or a **funding/enrollment**
|
|
13
|
+
* source (it denotes participation in a program). Three buckets fall out per entity:
|
|
14
|
+
*
|
|
15
|
+
* - **enrolled** — resolves to BOTH an eligibility and a funding record.
|
|
16
|
+
* - **eligible, not enrolled** — an eligibility record with NO funding record resolving to it (the
|
|
17
|
+
* ANTI-JOIN).
|
|
18
|
+
* - **funded, not in the eligibility set** — a funding record with no eligibility record resolving to
|
|
19
|
+
* it.
|
|
20
|
+
*
|
|
21
|
+
* This is strictly a **set-membership reconciliation, never a determination.** We produce the
|
|
22
|
+
* reconciled join and surface the candidate set; what a gap MEANS — and whether it is real, a
|
|
23
|
+
* sampling artifact, or actionable — is entirely the data consumer's call. Nothing here is an
|
|
24
|
+
* allegation. {@link reconciliationReport} bakes that caveat in by construction.
|
|
25
|
+
*
|
|
26
|
+
* Pairs with {@link toMapHTML}: {@link reconciliationGeoJSON} tags each feature with its `bucket`,
|
|
27
|
+
* which the map auto-detects and colors categorically.
|
|
28
|
+
*/
|
|
29
|
+
import type { GeoJsonFeatureCollection, ResolvedEntity } from "./types.js";
|
|
30
|
+
/** The three reconciliation buckets an entity can fall into. */
|
|
31
|
+
export type ReconciliationBucket = "enrolled" | "eligible-not-enrolled" | "funded-not-eligible";
|
|
32
|
+
/** Which source labels denote eligibility vs funding/enrollment. */
|
|
33
|
+
export interface ReconcileConfig {
|
|
34
|
+
/** Source labels denoting membership in the base/eligibility set. */
|
|
35
|
+
eligibilitySources: readonly string[];
|
|
36
|
+
/** Source labels denoting enrollment / funding / program participation. */
|
|
37
|
+
fundingSources: readonly string[];
|
|
38
|
+
}
|
|
39
|
+
/** One entity, classified. */
|
|
40
|
+
export interface ReconciledEntity {
|
|
41
|
+
entity: ResolvedEntity;
|
|
42
|
+
/** Distinct provenance labels the entity's records span, sorted. */
|
|
43
|
+
sources: string[];
|
|
44
|
+
bucket: ReconciliationBucket;
|
|
45
|
+
}
|
|
46
|
+
export interface ReconciliationResult {
|
|
47
|
+
/** Entities that carry at least one eligibility- or funding-tagged source, each bucketed. */
|
|
48
|
+
reconciled: ReconciledEntity[];
|
|
49
|
+
counts: Record<ReconciliationBucket, number>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Bucket an entity from the source labels its records span. Returns `null` when the entity carries
|
|
53
|
+
* NO eligibility- or funding-tagged source (it is outside this reconciliation — e.g. a source the
|
|
54
|
+
* caller didn't assign a role) so callers can exclude it rather than silently miscount it.
|
|
55
|
+
*/
|
|
56
|
+
export declare function bucketOf(sources: Iterable<string>, config: ReconcileConfig): ReconciliationBucket | null;
|
|
57
|
+
/**
|
|
58
|
+
* Classify resolved entities into reconciliation buckets. Entities with no eligibility- or
|
|
59
|
+
* funding-tagged source are excluded (see {@link bucketOf}).
|
|
60
|
+
*/
|
|
61
|
+
export declare function reconcileCoverage(entities: readonly ResolvedEntity[], config: ReconcileConfig): ReconciliationResult;
|
|
62
|
+
/**
|
|
63
|
+
* GeoJSON of every located reconciled entity, each feature tagged with its `bucket` + `sources` —
|
|
64
|
+
* the shape {@link toMapHTML} colors categorically by bucket. Entities without a coordinate are
|
|
65
|
+
* skipped.
|
|
66
|
+
*/
|
|
67
|
+
export declare function reconciliationGeoJSON(result: ReconciliationResult): GeoJsonFeatureCollection;
|
|
68
|
+
export interface ReconciliationReportOptions {
|
|
69
|
+
/** H1 title. Default: "Coverage reconciliation — eligibility ↔ enrollment". */
|
|
70
|
+
title?: string;
|
|
71
|
+
/** An italic scope paragraph under the title (what the sources are, how they were scoped). */
|
|
72
|
+
scopeNote?: string;
|
|
73
|
+
/** A paragraph about the scorer choice (e.g. why the FS baseline, not the dedup GBT). */
|
|
74
|
+
scorerNote?: string;
|
|
75
|
+
/** A paragraph about sampling/capping, woven into the caveat. */
|
|
76
|
+
sampleNote?: string;
|
|
77
|
+
/** How many "eligible, not enrolled" rows to spot-check. Default 15. */
|
|
78
|
+
spotCheckLimit?: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A markdown reconciliation report: the bucket counts, the enrolled-rate floor, an anti-join
|
|
82
|
+
* spot-check, and — always, by construction — the neutral caveat. The deliverable is the anti-join
|
|
83
|
+
* SET, not a rate, and never an allegation.
|
|
84
|
+
*/
|
|
85
|
+
export declare function reconciliationReport(result: ReconciliationResult, options?: ReconciliationReportOptions): string;
|
|
86
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE1E,gEAAgE;AAChE,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,uBAAuB,GAAG,qBAAqB,CAAA;AAE/F,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC/B,qEAAqE;IACrE,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,2EAA2E;IAC3E,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;CACjC;AAED,8BAA8B;AAC9B,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,cAAc,CAAA;IACtB,oEAAoE;IACpE,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,MAAM,EAAE,oBAAoB,CAAA;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACpC,6FAA6F;IAC7F,UAAU,EAAE,gBAAgB,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAA;CAC5C;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,eAAe,GAAG,oBAAoB,GAAG,IAAI,CAaxG;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,EAAE,MAAM,EAAE,eAAe,GAAG,oBAAoB,CAepH;AASD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,oBAAoB,GAAG,wBAAwB,CAoB5F;AAED,MAAM,WAAW,2BAA2B;IAC3C,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8FAA8F;IAC9F,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,GAAE,2BAAgC,GAAG,MAAM,CA0DpH"}
|
package/out/reconcile.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Coverage reconciliation (#621) — the library home for what `scripts/record-matcher/
|
|
7
|
+
* coverage-reconciliation.ts` does inline, so the CLI (`registry --reconcile`) and any consumer
|
|
8
|
+
* can reuse it.
|
|
9
|
+
*
|
|
10
|
+
* Given entities already resolved ACROSS sources (#618), classify each by which KIND of source its
|
|
11
|
+
* records come from. You tag each source label as either an **eligibility** source (it denotes
|
|
12
|
+
* membership in some base set — e.g. registered providers/facilities) or a **funding/enrollment**
|
|
13
|
+
* source (it denotes participation in a program). Three buckets fall out per entity:
|
|
14
|
+
*
|
|
15
|
+
* - **enrolled** — resolves to BOTH an eligibility and a funding record.
|
|
16
|
+
* - **eligible, not enrolled** — an eligibility record with NO funding record resolving to it (the
|
|
17
|
+
* ANTI-JOIN).
|
|
18
|
+
* - **funded, not in the eligibility set** — a funding record with no eligibility record resolving to
|
|
19
|
+
* it.
|
|
20
|
+
*
|
|
21
|
+
* This is strictly a **set-membership reconciliation, never a determination.** We produce the
|
|
22
|
+
* reconciled join and surface the candidate set; what a gap MEANS — and whether it is real, a
|
|
23
|
+
* sampling artifact, or actionable — is entirely the data consumer's call. Nothing here is an
|
|
24
|
+
* allegation. {@link reconciliationReport} bakes that caveat in by construction.
|
|
25
|
+
*
|
|
26
|
+
* Pairs with {@link toMapHTML}: {@link reconciliationGeoJSON} tags each feature with its `bucket`,
|
|
27
|
+
* which the map auto-detects and colors categorically.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Bucket an entity from the source labels its records span. Returns `null` when the entity carries
|
|
31
|
+
* NO eligibility- or funding-tagged source (it is outside this reconciliation — e.g. a source the
|
|
32
|
+
* caller didn't assign a role) so callers can exclude it rather than silently miscount it.
|
|
33
|
+
*/
|
|
34
|
+
export function bucketOf(sources, config) {
|
|
35
|
+
const elig = new Set(config.eligibilitySources);
|
|
36
|
+
const fund = new Set(config.fundingSources);
|
|
37
|
+
let hasEligibility = false;
|
|
38
|
+
let hasFunding = false;
|
|
39
|
+
for (const s of sources) {
|
|
40
|
+
if (elig.has(s))
|
|
41
|
+
hasEligibility = true;
|
|
42
|
+
if (fund.has(s))
|
|
43
|
+
hasFunding = true;
|
|
44
|
+
}
|
|
45
|
+
if (hasEligibility && hasFunding)
|
|
46
|
+
return "enrolled";
|
|
47
|
+
if (hasEligibility)
|
|
48
|
+
return "eligible-not-enrolled";
|
|
49
|
+
if (hasFunding)
|
|
50
|
+
return "funded-not-eligible";
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Classify resolved entities into reconciliation buckets. Entities with no eligibility- or
|
|
55
|
+
* funding-tagged source are excluded (see {@link bucketOf}).
|
|
56
|
+
*/
|
|
57
|
+
export function reconcileCoverage(entities, config) {
|
|
58
|
+
const reconciled = [];
|
|
59
|
+
const counts = {
|
|
60
|
+
enrolled: 0,
|
|
61
|
+
"eligible-not-enrolled": 0,
|
|
62
|
+
"funded-not-eligible": 0,
|
|
63
|
+
};
|
|
64
|
+
for (const entity of entities) {
|
|
65
|
+
const sources = [...new Set(entity.records.map((r) => r.source).filter((s) => !!s))].sort();
|
|
66
|
+
const bucket = bucketOf(sources, config);
|
|
67
|
+
if (!bucket)
|
|
68
|
+
continue;
|
|
69
|
+
reconciled.push({ entity, sources, bucket });
|
|
70
|
+
counts[bucket]++;
|
|
71
|
+
}
|
|
72
|
+
return { reconciled, counts };
|
|
73
|
+
}
|
|
74
|
+
/** A display name for a reconciled entity's representative record. */
|
|
75
|
+
function repName(entity) {
|
|
76
|
+
const rep = entity.representative;
|
|
77
|
+
const person = [rep.name?.given, rep.name?.family].filter(Boolean).join(" ");
|
|
78
|
+
return rep.organization?.canonical ?? (person || rep.id);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* GeoJSON of every located reconciled entity, each feature tagged with its `bucket` + `sources` —
|
|
82
|
+
* the shape {@link toMapHTML} colors categorically by bucket. Entities without a coordinate are
|
|
83
|
+
* skipped.
|
|
84
|
+
*/
|
|
85
|
+
export function reconciliationGeoJSON(result) {
|
|
86
|
+
return {
|
|
87
|
+
type: "FeatureCollection",
|
|
88
|
+
features: result.reconciled
|
|
89
|
+
.filter((c) => c.entity.coordinate)
|
|
90
|
+
.map((c) => ({
|
|
91
|
+
type: "Feature",
|
|
92
|
+
geometry: {
|
|
93
|
+
type: "Point",
|
|
94
|
+
coordinates: [c.entity.coordinate.longitude, c.entity.coordinate.latitude],
|
|
95
|
+
},
|
|
96
|
+
properties: {
|
|
97
|
+
entityId: c.entity.id,
|
|
98
|
+
bucket: c.bucket,
|
|
99
|
+
sources: c.sources,
|
|
100
|
+
name: repName(c.entity),
|
|
101
|
+
recordCount: c.entity.records.length,
|
|
102
|
+
},
|
|
103
|
+
})),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A markdown reconciliation report: the bucket counts, the enrolled-rate floor, an anti-join
|
|
108
|
+
* spot-check, and — always, by construction — the neutral caveat. The deliverable is the anti-join
|
|
109
|
+
* SET, not a rate, and never an allegation.
|
|
110
|
+
*/
|
|
111
|
+
export function reconciliationReport(result, options = {}) {
|
|
112
|
+
const { counts, reconciled } = result;
|
|
113
|
+
const title = options.title ?? "Coverage reconciliation — eligibility ↔ enrollment";
|
|
114
|
+
const spotCheckLimit = options.spotCheckLimit ?? 15;
|
|
115
|
+
const eligibleTotal = counts.enrolled + counts["eligible-not-enrolled"];
|
|
116
|
+
const enrolledRate = eligibleTotal > 0 ? (100 * counts.enrolled) / eligibleTotal : 0;
|
|
117
|
+
const lines = [];
|
|
118
|
+
lines.push(`# ${title}`);
|
|
119
|
+
lines.push("");
|
|
120
|
+
if (options.scopeNote) {
|
|
121
|
+
lines.push(`_${options.scopeNote}_`);
|
|
122
|
+
lines.push("");
|
|
123
|
+
}
|
|
124
|
+
if (options.scorerNote) {
|
|
125
|
+
lines.push(options.scorerNote);
|
|
126
|
+
lines.push("");
|
|
127
|
+
}
|
|
128
|
+
lines.push(`## The reconciliation`);
|
|
129
|
+
lines.push("");
|
|
130
|
+
lines.push(`| bucket | entities | meaning |`);
|
|
131
|
+
lines.push(`|---|---:|---|`);
|
|
132
|
+
lines.push(`| **enrolled** | ${counts.enrolled} | resolves to an eligibility record AND a funding record |`);
|
|
133
|
+
lines.push(`| **eligible, not enrolled** | ${counts["eligible-not-enrolled"]} | eligibility record, no funding record resolved (the **anti-join**) |`);
|
|
134
|
+
lines.push(`| **funded, not in eligibility set** | ${counts["funded-not-eligible"]} | funding record, no eligibility record resolved |`);
|
|
135
|
+
lines.push("");
|
|
136
|
+
lines.push(`Of the ${eligibleTotal} entities with an eligibility record, ${enrolledRate.toFixed(1)}% also resolve to a ` +
|
|
137
|
+
`funding record — a **floor**, not a coverage rate (imperfect resolution + any sampling only ever miss ` +
|
|
138
|
+
`links, never invent them). The deliverable is the anti-join SET, not this percentage.`);
|
|
139
|
+
lines.push("");
|
|
140
|
+
lines.push(`## Anti-join spot-check — first ${spotCheckLimit} "eligible, not enrolled"`);
|
|
141
|
+
lines.push("");
|
|
142
|
+
lines.push(`| entity | sources | name | coordinate |`);
|
|
143
|
+
lines.push(`|---|---|---|---|`);
|
|
144
|
+
for (const c of reconciled.filter((x) => x.bucket === "eligible-not-enrolled").slice(0, spotCheckLimit)) {
|
|
145
|
+
const coord = c.entity.coordinate
|
|
146
|
+
? `${c.entity.coordinate.latitude.toFixed(4)}, ${c.entity.coordinate.longitude.toFixed(4)}`
|
|
147
|
+
: "—";
|
|
148
|
+
lines.push(`| ${c.entity.id} | ${c.sources.join(", ")} | ${repName(c.entity)} | ${coord} |`);
|
|
149
|
+
}
|
|
150
|
+
lines.push("");
|
|
151
|
+
lines.push(`## The caveat that matters`);
|
|
152
|
+
lines.push("");
|
|
153
|
+
const sample = options.sampleNote ? `${options.sampleNote} ` : "";
|
|
154
|
+
lines.push(`${sample}This is a **set-membership reconciliation, not a determination**. A missing funding record can mean ` +
|
|
155
|
+
`the entity didn't apply, applied under a name we didn't resolve, is ineligible, or any number of things. We ` +
|
|
156
|
+
`produce the reconciled join and surface the candidate set; **what a gap means, and whether to act on it, is ` +
|
|
157
|
+
`entirely the data consumer's call.** Nothing here is an allegation.`);
|
|
158
|
+
lines.push("");
|
|
159
|
+
return lines.join("\n");
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=reconcile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../reconcile.ts"],"names":[],"mappings":"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"}
|
package/out/resolve.d.ts
CHANGED
|
@@ -125,9 +125,9 @@ export interface ResolveConfig {
|
|
|
125
125
|
* Override the Fellegi-Sunter link weight with a LEARNED score (#603). When set, a candidate
|
|
126
126
|
* pair's match weight is this function's return value (same threshold-comparable units as the FS
|
|
127
127
|
* weight) instead of {@link scorePair}'s. Default undefined (pure FS). The blocking + clustering
|
|
128
|
-
* are unchanged, so a trained scorer can be A/B'd against the FS
|
|
129
|
-
* The function is responsible for its own feature computation (e.g. the agreement
|
|
130
|
-
* is EM-independent, plus any corpus statistics it captured).
|
|
128
|
+
* are unchanged, so a trained scorer can be A/B'd against the FS baseline on the identical
|
|
129
|
+
* pipeline. The function is responsible for its own feature computation (e.g. the agreement
|
|
130
|
+
* pattern, which is EM-independent, plus any corpus statistics it captured).
|
|
131
131
|
*
|
|
132
132
|
* INTERACTION with {@link requireCorroboration}: the two are independent and compose, but the
|
|
133
133
|
* corroboration gate is still evaluated on the Fellegi-Sunter `contributions` (NOT the learned
|
|
@@ -139,12 +139,12 @@ export interface ResolveConfig {
|
|
|
139
139
|
/**
|
|
140
140
|
* **#603: the LEARNED gradient-boosted-tree scorer — DEFAULT-ON.** Omitted or `true` uses the
|
|
141
141
|
* bundled {@link DEDUP_GBT_MODEL} (trained on the NPPES NPI-truth set; beats the Fellegi-Sunter
|
|
142
|
-
*
|
|
143
|
-
* the co-located over-merge). `false` opts out to the pure FS
|
|
144
|
-
* a custom model. The scorer is built over the SAME collapsed-spatial +
|
|
145
|
-
* model as training (via the resolved {@link addressFrequency}),
|
|
146
|
-
* comparison config. An explicit {@link scorer} takes precedence. When
|
|
147
|
-
* and you don't set {@link threshold}, its CALIBRATED link threshold
|
|
142
|
+
* baseline ~+5pp dedup F1 held-out within a state and ~+22pp on states it never trained on,
|
|
143
|
+
* cutting the co-located over-merge). `false` opts out to the pure FS baseline; pass your own
|
|
144
|
+
* {@link GBT} for a custom model. The scorer is built over the SAME collapsed-spatial +
|
|
145
|
+
* address-frequency feature model as training (via the resolved {@link addressFrequency}),
|
|
146
|
+
* independent of this call's comparison config. An explicit {@link scorer} takes precedence. When
|
|
147
|
+
* the bundled model is active and you don't set {@link threshold}, its CALIBRATED link threshold
|
|
148
148
|
* ({@link DEDUP_GBT_META}.recommendedThreshold) is used — the GBT logit isn't in FS-weight units,
|
|
149
149
|
* so 0 would over-merge. The model is NPPES/US-trained; for a very different domain, A/B it or
|
|
150
150
|
* pass `false`.
|
package/out/resolve.js
CHANGED
|
@@ -163,7 +163,7 @@ export function resolveEntities(records, config = {}) {
|
|
|
163
163
|
});
|
|
164
164
|
const blockingKeys = config.blockingKeys ?? defaultBlockingKeys();
|
|
165
165
|
// #603: the learned scorer is DEFAULT-ON. An explicit `scorer` overrides everything; otherwise
|
|
166
|
-
// `learnedScorer === false` opts out to the FS
|
|
166
|
+
// `learnedScorer === false` opts out to the FS baseline, a GBT supplies a custom model, and
|
|
167
167
|
// `true`/omitted uses the bundled DEDUP_GBT_MODEL. The scorer is built over the FIXED
|
|
168
168
|
// collapsed-spatial + address-frequency feature model (matching training, independent of this call's
|
|
169
169
|
// comparison config), using the resolved address-frequency table.
|
|
@@ -179,7 +179,7 @@ export function resolveEntities(records, config = {}) {
|
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
181
|
// Threshold: an explicit value wins; else the bundled model's CALIBRATED threshold when it's active
|
|
182
|
-
// (its logit isn't in FS-weight units, so 0 would over-merge); else 0 (FS
|
|
182
|
+
// (its logit isn't in FS-weight units, so 0 would over-merge); else 0 (FS baseline or a custom model).
|
|
183
183
|
const threshold = config.threshold ?? (usingBundledModel ? DEDUP_GBT_META.recommendedThreshold : 0);
|
|
184
184
|
const { pairs, droppedBlocks } = block(records, blockingKeys, { maxBlockSize: config.maxBlockSize });
|
|
185
185
|
let scoringModel = model;
|
package/out/resolve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../resolve.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../resolve.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mailwoman/registry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.12.0",
|
|
4
4
|
"description": "The geocode-first record-matching application: resolve messy contact/organization records into canonical, geocoded entities (block → score → cluster) and export them as GeoJSON for spatial analysis. The clinic-funding use case mailwoman was built for.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
"./ingest": "./out/ingest.js"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@mailwoman/address-id": "4.
|
|
21
|
-
"@mailwoman/match": "4.
|
|
22
|
-
"@mailwoman/record": "4.
|
|
20
|
+
"@mailwoman/address-id": "4.12.0",
|
|
21
|
+
"@mailwoman/match": "4.12.0",
|
|
22
|
+
"@mailwoman/record": "4.12.0",
|
|
23
|
+
"@protomaps/basemaps": "^5.7.2",
|
|
23
24
|
"csv-parse": "^5.6.0",
|
|
24
25
|
"spliterator": "^2.0.0"
|
|
25
26
|
},
|