@mailwoman/geographic-model 0.0.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 +155 -0
- package/artifact.ts +198 -0
- package/compile.ts +350 -0
- package/data/geographic-model.json +172 -0
- package/data/model/concepts.json +114 -0
- package/data/model/mappings.json +18 -0
- package/data/model/model.json +3 -0
- package/data/model/relations.json +14 -0
- package/index.ts +51 -0
- package/load.ts +396 -0
- package/lookup.ts +129 -0
- package/out/artifact.d.ts +106 -0
- package/out/artifact.d.ts.map +1 -0
- package/out/artifact.js +135 -0
- package/out/artifact.js.map +1 -0
- package/out/compile.d.ts +84 -0
- package/out/compile.d.ts.map +1 -0
- package/out/compile.js +259 -0
- package/out/compile.js.map +1 -0
- package/out/index.d.ts +51 -0
- package/out/index.d.ts.map +1 -0
- package/out/index.js +51 -0
- package/out/index.js.map +1 -0
- package/out/load.d.ts +122 -0
- package/out/load.d.ts.map +1 -0
- package/out/load.js +269 -0
- package/out/load.js.map +1 -0
- package/out/lookup.d.ts +64 -0
- package/out/lookup.d.ts.map +1 -0
- package/out/lookup.js +68 -0
- package/out/lookup.js.map +1 -0
- package/out/schema.d.ts +366 -0
- package/out/schema.d.ts.map +1 -0
- package/out/schema.js +166 -0
- package/out/schema.js.map +1 -0
- package/out/scripts/build-artifact.d.ts +51 -0
- package/out/scripts/build-artifact.d.ts.map +1 -0
- package/out/scripts/build-artifact.js +78 -0
- package/out/scripts/build-artifact.js.map +1 -0
- package/out/validate.d.ts +67 -0
- package/out/validate.d.ts.map +1 -0
- package/out/validate.js +465 -0
- package/out/validate.js.map +1 -0
- package/out/validation-issues.d.ts +84 -0
- package/out/validation-issues.d.ts.map +1 -0
- package/out/validation-issues.js +190 -0
- package/out/validation-issues.js.map +1 -0
- package/package.json +120 -0
- package/schema.ts +399 -0
- package/validate.ts +845 -0
- package/validation-issues.ts +305 -0
package/out/schema.d.ts
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* The authored-record schema for `@mailwoman/geographic-model`: the stable identifiers, the closed
|
|
7
|
+
* vocabularies, and the record shapes for concepts, relations, external-vocabulary mappings, source
|
|
8
|
+
* observations, and derived facts.
|
|
9
|
+
*
|
|
10
|
+
* Three properties hold by construction, and they are why the file reads the way it does.
|
|
11
|
+
*
|
|
12
|
+
* **No numeric field exists anywhere in this schema** — not a strength, not a confidence, not a
|
|
13
|
+
* count. {@link Modality} is an ordinal vocabulary of WORDS and this module exports no order over
|
|
14
|
+
* it, because a number attached to an authored relationship is a ranking weight whatever it is
|
|
15
|
+
* called, and ranking belongs to `@mailwoman/resolver` and `@mailwoman/neural`.
|
|
16
|
+
*
|
|
17
|
+
* **An authored assertion, a source observation, and a derived fact are three different types.** A
|
|
18
|
+
* {@link RelationAssertion} is authored by a curator and lives on the concept it is about; a
|
|
19
|
+
* {@link SourceObservationRecord} records what a named external source states and never enters the
|
|
20
|
+
* concept table; a {@link DerivedFactRecord} names the procedure that produced it and every input
|
|
21
|
+
* that procedure read. Their identifiers are separately branded, so one is not assignable where
|
|
22
|
+
* another is expected.
|
|
23
|
+
*
|
|
24
|
+
* **Every record carries provenance, and a derived fact carries it structurally.** A derived fact
|
|
25
|
+
* has no {@link SourceProvenance} of its own: its `derivation` plus its resolved `inputs` ARE its
|
|
26
|
+
* provenance, and each input carries source provenance in turn.
|
|
27
|
+
*
|
|
28
|
+
* Identifier namespaces are per-table. A {@link ConceptID} and a {@link RelationID} may read the
|
|
29
|
+
* same string without colliding; the brands are what keep them apart in a consumer.
|
|
30
|
+
*
|
|
31
|
+
* Consumed by `./validate.ts` (which refuses a document violating any rule above), by #1926's
|
|
32
|
+
* deterministic compiler, and by the first authored document in #1927.
|
|
33
|
+
*
|
|
34
|
+
* Boundary record: `docs/superpowers/specs/2026-08-26-geographic-model-boundaries.md` (#1917).
|
|
35
|
+
*/
|
|
36
|
+
import type { POICategoryID } from "@mailwoman/poi-taxonomy/types";
|
|
37
|
+
import type { Tagged } from "type-fest";
|
|
38
|
+
/**
|
|
39
|
+
* A concept identifier, e.g. `pharmacy`, `obtain_medication`. Branded — convert via {@link toConceptID}.
|
|
40
|
+
*/
|
|
41
|
+
export type ConceptID = Tagged<string, "GeographicConceptID">;
|
|
42
|
+
/**
|
|
43
|
+
* Brand a raw string as a {@link ConceptID}. Purely a compile-time assertion; the string is unchanged.
|
|
44
|
+
*/
|
|
45
|
+
export declare function toConceptID(id: string): ConceptID;
|
|
46
|
+
/**
|
|
47
|
+
* A relation identifier, e.g. `affords`. Branded — convert via {@link toRelationID}.
|
|
48
|
+
*/
|
|
49
|
+
export type RelationID = Tagged<string, "GeographicRelationID">;
|
|
50
|
+
/**
|
|
51
|
+
* Brand a raw string as a {@link RelationID}. Purely a compile-time assertion; the string is unchanged.
|
|
52
|
+
*/
|
|
53
|
+
export declare function toRelationID(id: string): RelationID;
|
|
54
|
+
/**
|
|
55
|
+
* The identifier of one authored {@link RelationAssertion}. Branded — convert via {@link toRuleID}.
|
|
56
|
+
*/
|
|
57
|
+
export type RuleID = Tagged<string, "GeographicRuleID">;
|
|
58
|
+
/**
|
|
59
|
+
* Brand a raw string as a {@link RuleID}. Purely a compile-time assertion; the string is unchanged.
|
|
60
|
+
*/
|
|
61
|
+
export declare function toRuleID(id: string): RuleID;
|
|
62
|
+
/**
|
|
63
|
+
* The identifier of one {@link ExternalMappingRecord}. Branded — convert via {@link toMappingID}.
|
|
64
|
+
*/
|
|
65
|
+
export type MappingID = Tagged<string, "GeographicMappingID">;
|
|
66
|
+
/**
|
|
67
|
+
* Brand a raw string as a {@link MappingID}. Purely a compile-time assertion; the string is unchanged.
|
|
68
|
+
*/
|
|
69
|
+
export declare function toMappingID(id: string): MappingID;
|
|
70
|
+
/**
|
|
71
|
+
* The identifier of one {@link SourceObservationRecord}. Branded — convert via {@link toObservationID}.
|
|
72
|
+
*/
|
|
73
|
+
export type ObservationID = Tagged<string, "GeographicObservationID">;
|
|
74
|
+
/**
|
|
75
|
+
* Brand a raw string as an {@link ObservationID}. Purely a compile-time assertion; the string is unchanged.
|
|
76
|
+
*/
|
|
77
|
+
export declare function toObservationID(id: string): ObservationID;
|
|
78
|
+
/**
|
|
79
|
+
* The identifier of one {@link DerivedFactRecord}. Branded — convert via {@link toDerivedFactID}.
|
|
80
|
+
*/
|
|
81
|
+
export type DerivedFactID = Tagged<string, "GeographicDerivedFactID">;
|
|
82
|
+
/**
|
|
83
|
+
* Brand a raw string as a {@link DerivedFactID}. Purely a compile-time assertion; the string is unchanged.
|
|
84
|
+
*/
|
|
85
|
+
export declare function toDerivedFactID(id: string): DerivedFactID;
|
|
86
|
+
/**
|
|
87
|
+
* The complete set of concept kinds. Three, deliberately: the first executable slice needs an establishment class, an
|
|
88
|
+
* activity, and the place class an establishment is sited in. Widening this vocabulary is a reviewed schema revision,
|
|
89
|
+
* which is the review cost the program accepted in exchange for refusing speculative upper-ontology breadth.
|
|
90
|
+
*/
|
|
91
|
+
export declare const ConceptKind: {
|
|
92
|
+
/**
|
|
93
|
+
* A geographic place — an area or a point that other things are sited in or near.
|
|
94
|
+
*/
|
|
95
|
+
readonly Place: "place";
|
|
96
|
+
/**
|
|
97
|
+
* A class of premises a person can go to, e.g. `pharmacy`.
|
|
98
|
+
*/
|
|
99
|
+
readonly Establishment: "establishment";
|
|
100
|
+
/**
|
|
101
|
+
* Something a person does, e.g. `obtain_medication`. The identifier is owned here; any statistics fitted against it
|
|
102
|
+
* are owned by #1683.
|
|
103
|
+
*/
|
|
104
|
+
readonly Activity: "activity";
|
|
105
|
+
};
|
|
106
|
+
export type ConceptKind = (typeof ConceptKind)[keyof typeof ConceptKind];
|
|
107
|
+
/**
|
|
108
|
+
* How strongly an assertion, an observation, or a derived fact claims its proposition holds.
|
|
109
|
+
*
|
|
110
|
+
* The vocabulary is ordinal in meaning and this module exports no order over it, on purpose. An exported rank would be
|
|
111
|
+
* one arithmetic step from a weight, and an authored weight is the single thing the package boundary forbids.
|
|
112
|
+
*/
|
|
113
|
+
export declare const Modality: {
|
|
114
|
+
/**
|
|
115
|
+
* Holds in every instance; a counter-example falsifies the record rather than qualifying it.
|
|
116
|
+
*/
|
|
117
|
+
readonly Necessary: "necessary";
|
|
118
|
+
/**
|
|
119
|
+
* Never holds.
|
|
120
|
+
*/
|
|
121
|
+
readonly Prohibited: "prohibited";
|
|
122
|
+
readonly StronglyExpected: "strongly_expected";
|
|
123
|
+
readonly Expected: "expected";
|
|
124
|
+
readonly WeaklyExpected: "weakly_expected";
|
|
125
|
+
/**
|
|
126
|
+
* Consistent with the concept and asserts nothing about how often it holds.
|
|
127
|
+
*/
|
|
128
|
+
readonly Possible: "possible";
|
|
129
|
+
readonly Unusual: "unusual";
|
|
130
|
+
readonly StronglyUnusual: "strongly_unusual";
|
|
131
|
+
};
|
|
132
|
+
export type Modality = (typeof Modality)[keyof typeof Modality];
|
|
133
|
+
/**
|
|
134
|
+
* Whether a relation's assertions admit exceptions.
|
|
135
|
+
*/
|
|
136
|
+
export declare const RelationSemantics: {
|
|
137
|
+
/**
|
|
138
|
+
* An exception is a defect in the record set.
|
|
139
|
+
*/
|
|
140
|
+
readonly Hard: "hard";
|
|
141
|
+
/**
|
|
142
|
+
* An exception is expected and does not falsify the relation.
|
|
143
|
+
*/
|
|
144
|
+
readonly Defeasible: "defeasible";
|
|
145
|
+
};
|
|
146
|
+
export type RelationSemantics = (typeof RelationSemantics)[keyof typeof RelationSemantics];
|
|
147
|
+
/**
|
|
148
|
+
* A concept's authoring lifecycle. It says whether a consumer should read the record, and nothing about how much the
|
|
149
|
+
* record is worth.
|
|
150
|
+
*/
|
|
151
|
+
export declare const ConceptStatus: {
|
|
152
|
+
/**
|
|
153
|
+
* Authored, not yet reviewed. A compiler may refuse to emit it.
|
|
154
|
+
*/
|
|
155
|
+
readonly Draft: "draft";
|
|
156
|
+
readonly Active: "active";
|
|
157
|
+
/**
|
|
158
|
+
* Kept so existing references resolve; no new reference should be authored against it.
|
|
159
|
+
*/
|
|
160
|
+
readonly Deprecated: "deprecated";
|
|
161
|
+
};
|
|
162
|
+
export type ConceptStatus = (typeof ConceptStatus)[keyof typeof ConceptStatus];
|
|
163
|
+
/**
|
|
164
|
+
* The external vocabularies a concept can be mapped into. One today, and the mapping record below is typed against it
|
|
165
|
+
* directly; a second vocabulary turns {@link ExternalMappingRecord} into a union discriminated on `vocabulary`.
|
|
166
|
+
*/
|
|
167
|
+
export declare const ExternalVocabulary: {
|
|
168
|
+
/**
|
|
169
|
+
* `@mailwoman/poi-taxonomy` category identifiers — the owner of external and curated POI categories.
|
|
170
|
+
*/
|
|
171
|
+
readonly POITaxonomy: "poi-taxonomy";
|
|
172
|
+
};
|
|
173
|
+
export type ExternalVocabulary = (typeof ExternalVocabulary)[keyof typeof ExternalVocabulary];
|
|
174
|
+
/**
|
|
175
|
+
* Where a record came from. `source` is required and non-empty on every record that carries provenance: a record whose
|
|
176
|
+
* source is blank is indistinguishable from a record nobody stands behind.
|
|
177
|
+
*/
|
|
178
|
+
export interface SourceProvenance {
|
|
179
|
+
/**
|
|
180
|
+
* The naming authority, dataset, publication, or curator, e.g. `overture-places` or `mailwoman-curated`.
|
|
181
|
+
*/
|
|
182
|
+
source: string;
|
|
183
|
+
/**
|
|
184
|
+
* The source's own version or release string, when it has one, e.g. an Overture release.
|
|
185
|
+
*/
|
|
186
|
+
sourceVersion?: string;
|
|
187
|
+
/**
|
|
188
|
+
* The identifier of the specific record within the source, when the claim is traceable to one.
|
|
189
|
+
*/
|
|
190
|
+
sourceRecord?: string;
|
|
191
|
+
sourceURL?: string;
|
|
192
|
+
/**
|
|
193
|
+
* ISO 8601 calendar date the record was authored, `YYYY-MM-DD`.
|
|
194
|
+
*/
|
|
195
|
+
authoredAt?: string;
|
|
196
|
+
notes?: string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* One relation's definition. Relations are vocabulary, not claims: the record says what the relation MEANS and which
|
|
200
|
+
* concept kinds may stand on either side of it, and asserts nothing about any particular pair.
|
|
201
|
+
*/
|
|
202
|
+
export interface RelationRecord {
|
|
203
|
+
id: RelationID;
|
|
204
|
+
label: string;
|
|
205
|
+
description: string;
|
|
206
|
+
/**
|
|
207
|
+
* The concept kinds allowed on the asserting side.
|
|
208
|
+
*/
|
|
209
|
+
domainKinds: ConceptKind[];
|
|
210
|
+
/**
|
|
211
|
+
* The concept kinds allowed on the target side.
|
|
212
|
+
*/
|
|
213
|
+
rangeKinds: ConceptKind[];
|
|
214
|
+
transitive: boolean;
|
|
215
|
+
symmetric: boolean;
|
|
216
|
+
/**
|
|
217
|
+
* The relation reading the same edge in the other direction. When present it must resolve, and the relation it names
|
|
218
|
+
* must name this one back.
|
|
219
|
+
*/
|
|
220
|
+
inverse?: RelationID;
|
|
221
|
+
semantics: RelationSemantics;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* One authored claim, attached to the concept it is about. This is curated semantics — what a curator states holds, not
|
|
225
|
+
* what a dataset was observed to contain.
|
|
226
|
+
*/
|
|
227
|
+
export interface RelationAssertion {
|
|
228
|
+
id: RuleID;
|
|
229
|
+
relation: RelationID;
|
|
230
|
+
target: ConceptID;
|
|
231
|
+
modality: Modality;
|
|
232
|
+
/**
|
|
233
|
+
* ISO 3166-1 alpha-2 codes the claim is scoped to. Absent means the curator scoped it to nowhere in particular, which
|
|
234
|
+
* is a weaker statement than scoping it to everywhere.
|
|
235
|
+
*/
|
|
236
|
+
countries?: string[];
|
|
237
|
+
provenance: SourceProvenance;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* One concept, and everything authored about it.
|
|
241
|
+
*/
|
|
242
|
+
export interface ConceptRecord {
|
|
243
|
+
id: ConceptID;
|
|
244
|
+
label: string;
|
|
245
|
+
description: string;
|
|
246
|
+
kind: ConceptKind;
|
|
247
|
+
/**
|
|
248
|
+
* Broader concepts this one is a kind of. May be empty; may not name this concept, directly or around a cycle.
|
|
249
|
+
*/
|
|
250
|
+
isA: ConceptID[];
|
|
251
|
+
assertions: RelationAssertion[];
|
|
252
|
+
provenance: SourceProvenance;
|
|
253
|
+
status: ConceptStatus;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* A translation from an external vocabulary's identifier into a concept owned here. It carries no semantics of its own:
|
|
257
|
+
* it says which external identifier names the same thing, and on whose authority.
|
|
258
|
+
*/
|
|
259
|
+
export interface ExternalMappingRecord {
|
|
260
|
+
id: MappingID;
|
|
261
|
+
concept: ConceptID;
|
|
262
|
+
vocabulary: ExternalVocabulary;
|
|
263
|
+
/**
|
|
264
|
+
* The identifier in the external vocabulary. Typed as a `POICategoryID` because `poi-taxonomy` is the only member of
|
|
265
|
+
* {@link ExternalVocabulary}; a second member makes this field a per-vocabulary type.
|
|
266
|
+
*/
|
|
267
|
+
externalID: POICategoryID;
|
|
268
|
+
provenance: SourceProvenance;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* A proposition a named external source states, recorded in this model's vocabulary.
|
|
272
|
+
*
|
|
273
|
+
* It is kept out of the concept table on purpose. An observation is evidence about the world that someone else
|
|
274
|
+
* collected; promoting one into an authored assertion is a curation decision that has to be made and provenanced
|
|
275
|
+
* explicitly, never by the record sitting in a convenient place.
|
|
276
|
+
*/
|
|
277
|
+
export interface SourceObservationRecord {
|
|
278
|
+
id: ObservationID;
|
|
279
|
+
subject: ConceptID;
|
|
280
|
+
relation: RelationID;
|
|
281
|
+
object: ConceptID;
|
|
282
|
+
modality: Modality;
|
|
283
|
+
/**
|
|
284
|
+
* ISO 3166-1 alpha-2 codes the source scoped its statement to.
|
|
285
|
+
*/
|
|
286
|
+
countries?: string[];
|
|
287
|
+
provenance: SourceProvenance;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Which table a {@link DerivationInput} points into.
|
|
291
|
+
*/
|
|
292
|
+
export declare const DerivationInputKind: {
|
|
293
|
+
readonly Concept: "concept";
|
|
294
|
+
readonly Relation: "relation";
|
|
295
|
+
readonly Assertion: "assertion";
|
|
296
|
+
readonly Mapping: "mapping";
|
|
297
|
+
readonly Observation: "observation";
|
|
298
|
+
readonly DerivedFact: "derived_fact";
|
|
299
|
+
};
|
|
300
|
+
export type DerivationInputKind = (typeof DerivationInputKind)[keyof typeof DerivationInputKind];
|
|
301
|
+
/**
|
|
302
|
+
* One record a derivation read. The union is discriminated on `kind` so the identifier's brand matches the table it
|
|
303
|
+
* resolves against.
|
|
304
|
+
*/
|
|
305
|
+
export type DerivationInput = {
|
|
306
|
+
kind: typeof DerivationInputKind.Concept;
|
|
307
|
+
id: ConceptID;
|
|
308
|
+
} | {
|
|
309
|
+
kind: typeof DerivationInputKind.Relation;
|
|
310
|
+
id: RelationID;
|
|
311
|
+
} | {
|
|
312
|
+
kind: typeof DerivationInputKind.Assertion;
|
|
313
|
+
id: RuleID;
|
|
314
|
+
} | {
|
|
315
|
+
kind: typeof DerivationInputKind.Mapping;
|
|
316
|
+
id: MappingID;
|
|
317
|
+
} | {
|
|
318
|
+
kind: typeof DerivationInputKind.Observation;
|
|
319
|
+
id: ObservationID;
|
|
320
|
+
} | {
|
|
321
|
+
kind: typeof DerivationInputKind.DerivedFact;
|
|
322
|
+
id: DerivedFactID;
|
|
323
|
+
};
|
|
324
|
+
/**
|
|
325
|
+
* A fact a named procedure computed from named inputs. Never hand-authored: #1926's compiler writes this table, and the
|
|
326
|
+
* validator refuses a fact whose derivation is unnamed or whose inputs do not resolve.
|
|
327
|
+
*
|
|
328
|
+
* There is no provenance field. The derivation plus the inputs is the provenance, and it is the stronger kind — a
|
|
329
|
+
* source string can be copied onto a record that did not come from it, while an input list either resolves or the
|
|
330
|
+
* document does not validate.
|
|
331
|
+
*/
|
|
332
|
+
export interface DerivedFactRecord {
|
|
333
|
+
id: DerivedFactID;
|
|
334
|
+
/**
|
|
335
|
+
* The deterministic procedure that produced this fact, named so a reader can re-run it.
|
|
336
|
+
*/
|
|
337
|
+
derivation: string;
|
|
338
|
+
/**
|
|
339
|
+
* Every record the derivation read. At least one, and each must resolve.
|
|
340
|
+
*/
|
|
341
|
+
inputs: DerivationInput[];
|
|
342
|
+
subject: ConceptID;
|
|
343
|
+
relation: RelationID;
|
|
344
|
+
object: ConceptID;
|
|
345
|
+
modality: Modality;
|
|
346
|
+
countries?: string[];
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* One authored document: the whole record set a validator, and later a compiler, reads at once.
|
|
350
|
+
*
|
|
351
|
+
* All six fields are required, `derivedFacts` included. A hand-authored file therefore writes `"derivedFacts": []`,
|
|
352
|
+
* which is the point — an absent table and an empty table are different claims, and the format that allows the first to
|
|
353
|
+
* stand in for the second is the format where a dropped table reads as a world with no derived facts in it.
|
|
354
|
+
*/
|
|
355
|
+
export interface GeographicModelDocument {
|
|
356
|
+
/**
|
|
357
|
+
* The document's own schema/data version.
|
|
358
|
+
*/
|
|
359
|
+
version: string;
|
|
360
|
+
relations: RelationRecord[];
|
|
361
|
+
concepts: ConceptRecord[];
|
|
362
|
+
mappings: ExternalMappingRecord[];
|
|
363
|
+
observations: SourceObservationRecord[];
|
|
364
|
+
derivedFacts: DerivedFactRecord[];
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../schema.ts"],"names":[],"mappings":"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"}
|
package/out/schema.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* The authored-record schema for `@mailwoman/geographic-model`: the stable identifiers, the closed
|
|
7
|
+
* vocabularies, and the record shapes for concepts, relations, external-vocabulary mappings, source
|
|
8
|
+
* observations, and derived facts.
|
|
9
|
+
*
|
|
10
|
+
* Three properties hold by construction, and they are why the file reads the way it does.
|
|
11
|
+
*
|
|
12
|
+
* **No numeric field exists anywhere in this schema** — not a strength, not a confidence, not a
|
|
13
|
+
* count. {@link Modality} is an ordinal vocabulary of WORDS and this module exports no order over
|
|
14
|
+
* it, because a number attached to an authored relationship is a ranking weight whatever it is
|
|
15
|
+
* called, and ranking belongs to `@mailwoman/resolver` and `@mailwoman/neural`.
|
|
16
|
+
*
|
|
17
|
+
* **An authored assertion, a source observation, and a derived fact are three different types.** A
|
|
18
|
+
* {@link RelationAssertion} is authored by a curator and lives on the concept it is about; a
|
|
19
|
+
* {@link SourceObservationRecord} records what a named external source states and never enters the
|
|
20
|
+
* concept table; a {@link DerivedFactRecord} names the procedure that produced it and every input
|
|
21
|
+
* that procedure read. Their identifiers are separately branded, so one is not assignable where
|
|
22
|
+
* another is expected.
|
|
23
|
+
*
|
|
24
|
+
* **Every record carries provenance, and a derived fact carries it structurally.** A derived fact
|
|
25
|
+
* has no {@link SourceProvenance} of its own: its `derivation` plus its resolved `inputs` ARE its
|
|
26
|
+
* provenance, and each input carries source provenance in turn.
|
|
27
|
+
*
|
|
28
|
+
* Identifier namespaces are per-table. A {@link ConceptID} and a {@link RelationID} may read the
|
|
29
|
+
* same string without colliding; the brands are what keep them apart in a consumer.
|
|
30
|
+
*
|
|
31
|
+
* Consumed by `./validate.ts` (which refuses a document violating any rule above), by #1926's
|
|
32
|
+
* deterministic compiler, and by the first authored document in #1927.
|
|
33
|
+
*
|
|
34
|
+
* Boundary record: `docs/superpowers/specs/2026-08-26-geographic-model-boundaries.md` (#1917).
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Brand a raw string as a {@link ConceptID}. Purely a compile-time assertion; the string is unchanged.
|
|
38
|
+
*/
|
|
39
|
+
export function toConceptID(id) {
|
|
40
|
+
return id;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Brand a raw string as a {@link RelationID}. Purely a compile-time assertion; the string is unchanged.
|
|
44
|
+
*/
|
|
45
|
+
export function toRelationID(id) {
|
|
46
|
+
return id;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Brand a raw string as a {@link RuleID}. Purely a compile-time assertion; the string is unchanged.
|
|
50
|
+
*/
|
|
51
|
+
export function toRuleID(id) {
|
|
52
|
+
return id;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Brand a raw string as a {@link MappingID}. Purely a compile-time assertion; the string is unchanged.
|
|
56
|
+
*/
|
|
57
|
+
export function toMappingID(id) {
|
|
58
|
+
return id;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Brand a raw string as an {@link ObservationID}. Purely a compile-time assertion; the string is unchanged.
|
|
62
|
+
*/
|
|
63
|
+
export function toObservationID(id) {
|
|
64
|
+
return id;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Brand a raw string as a {@link DerivedFactID}. Purely a compile-time assertion; the string is unchanged.
|
|
68
|
+
*/
|
|
69
|
+
export function toDerivedFactID(id) {
|
|
70
|
+
return id;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The complete set of concept kinds. Three, deliberately: the first executable slice needs an establishment class, an
|
|
74
|
+
* activity, and the place class an establishment is sited in. Widening this vocabulary is a reviewed schema revision,
|
|
75
|
+
* which is the review cost the program accepted in exchange for refusing speculative upper-ontology breadth.
|
|
76
|
+
*/
|
|
77
|
+
export const ConceptKind = {
|
|
78
|
+
/**
|
|
79
|
+
* A geographic place — an area or a point that other things are sited in or near.
|
|
80
|
+
*/
|
|
81
|
+
Place: "place",
|
|
82
|
+
/**
|
|
83
|
+
* A class of premises a person can go to, e.g. `pharmacy`.
|
|
84
|
+
*/
|
|
85
|
+
Establishment: "establishment",
|
|
86
|
+
/**
|
|
87
|
+
* Something a person does, e.g. `obtain_medication`. The identifier is owned here; any statistics fitted against it
|
|
88
|
+
* are owned by #1683.
|
|
89
|
+
*/
|
|
90
|
+
Activity: "activity",
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* How strongly an assertion, an observation, or a derived fact claims its proposition holds.
|
|
94
|
+
*
|
|
95
|
+
* The vocabulary is ordinal in meaning and this module exports no order over it, on purpose. An exported rank would be
|
|
96
|
+
* one arithmetic step from a weight, and an authored weight is the single thing the package boundary forbids.
|
|
97
|
+
*/
|
|
98
|
+
export const Modality = {
|
|
99
|
+
/**
|
|
100
|
+
* Holds in every instance; a counter-example falsifies the record rather than qualifying it.
|
|
101
|
+
*/
|
|
102
|
+
Necessary: "necessary",
|
|
103
|
+
/**
|
|
104
|
+
* Never holds.
|
|
105
|
+
*/
|
|
106
|
+
Prohibited: "prohibited",
|
|
107
|
+
StronglyExpected: "strongly_expected",
|
|
108
|
+
Expected: "expected",
|
|
109
|
+
WeaklyExpected: "weakly_expected",
|
|
110
|
+
/**
|
|
111
|
+
* Consistent with the concept and asserts nothing about how often it holds.
|
|
112
|
+
*/
|
|
113
|
+
Possible: "possible",
|
|
114
|
+
Unusual: "unusual",
|
|
115
|
+
StronglyUnusual: "strongly_unusual",
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Whether a relation's assertions admit exceptions.
|
|
119
|
+
*/
|
|
120
|
+
export const RelationSemantics = {
|
|
121
|
+
/**
|
|
122
|
+
* An exception is a defect in the record set.
|
|
123
|
+
*/
|
|
124
|
+
Hard: "hard",
|
|
125
|
+
/**
|
|
126
|
+
* An exception is expected and does not falsify the relation.
|
|
127
|
+
*/
|
|
128
|
+
Defeasible: "defeasible",
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* A concept's authoring lifecycle. It says whether a consumer should read the record, and nothing about how much the
|
|
132
|
+
* record is worth.
|
|
133
|
+
*/
|
|
134
|
+
export const ConceptStatus = {
|
|
135
|
+
/**
|
|
136
|
+
* Authored, not yet reviewed. A compiler may refuse to emit it.
|
|
137
|
+
*/
|
|
138
|
+
Draft: "draft",
|
|
139
|
+
Active: "active",
|
|
140
|
+
/**
|
|
141
|
+
* Kept so existing references resolve; no new reference should be authored against it.
|
|
142
|
+
*/
|
|
143
|
+
Deprecated: "deprecated",
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* The external vocabularies a concept can be mapped into. One today, and the mapping record below is typed against it
|
|
147
|
+
* directly; a second vocabulary turns {@link ExternalMappingRecord} into a union discriminated on `vocabulary`.
|
|
148
|
+
*/
|
|
149
|
+
export const ExternalVocabulary = {
|
|
150
|
+
/**
|
|
151
|
+
* `@mailwoman/poi-taxonomy` category identifiers — the owner of external and curated POI categories.
|
|
152
|
+
*/
|
|
153
|
+
POITaxonomy: "poi-taxonomy",
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Which table a {@link DerivationInput} points into.
|
|
157
|
+
*/
|
|
158
|
+
export const DerivationInputKind = {
|
|
159
|
+
Concept: "concept",
|
|
160
|
+
Relation: "relation",
|
|
161
|
+
Assertion: "assertion",
|
|
162
|
+
Mapping: "mapping",
|
|
163
|
+
Observation: "observation",
|
|
164
|
+
DerivedFact: "derived_fact",
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAUH;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACrC,OAAO,EAAe,CAAA;AACvB,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU;IACtC,OAAO,EAAgB,CAAA;AACxB,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAU;IAClC,OAAO,EAAY,CAAA;AACpB,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACrC,OAAO,EAAe,CAAA;AACvB,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAAU;IACzC,OAAO,EAAmB,CAAA;AAC3B,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAAU;IACzC,OAAO,EAAmB,CAAA;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B;;OAEG;IACH,KAAK,EAAE,OAAO;IACd;;OAEG;IACH,aAAa,EAAE,eAAe;IAC9B;;;OAGG;IACH,QAAQ,EAAE,UAAU;CACX,CAAA;AAIV;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACvB;;OAEG;IACH,SAAS,EAAE,WAAW;IACtB;;OAEG;IACH,UAAU,EAAE,YAAY;IACxB,gBAAgB,EAAE,mBAAmB;IACrC,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,iBAAiB;IACjC;;OAEG;IACH,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,eAAe,EAAE,kBAAkB;CAC1B,CAAA;AAIV;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM;IACZ;;OAEG;IACH,UAAU,EAAE,YAAY;CACf,CAAA;AAIV;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B;;OAEG;IACH,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB;;OAEG;IACH,UAAU,EAAE,YAAY;CACf,CAAA;AAIV;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IACjC;;OAEG;IACH,WAAW,EAAE,cAAc;CAClB,CAAA;AA6HV;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAClC,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,aAAa;IAC1B,WAAW,EAAE,cAAc;CAClB,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Generator for `data/geographic-model.json` — the committed compiled artifact, built from the
|
|
7
|
+
* authored records under `data/model/`.
|
|
8
|
+
*
|
|
9
|
+
* The build step is the whole of what this file does: load the authoring directory, compile it,
|
|
10
|
+
* serialize the result. Every decision inside those three calls belongs to `../load.ts`,
|
|
11
|
+
* `../compile.ts` and `../artifact.ts`, and none of them is re-made here.
|
|
12
|
+
*
|
|
13
|
+
* **A committed artifact is these bytes run through `oxfmt`.** The repository formatter also formats
|
|
14
|
+
* committed JSON, and it inlines short arrays, which `JSON.stringify` cannot reproduce. So the
|
|
15
|
+
* freshness check in `test/unit/pharmacy-slice.test.ts` compares the PARSED artifact against a fresh
|
|
16
|
+
* compile, and byte equality is asserted between two compiles instead. The same convention holds
|
|
17
|
+
* `taxonomy.json` in `@mailwoman/poi-taxonomy`; its `data/PROVENANCE.md` states it for that table.
|
|
18
|
+
*
|
|
19
|
+
* Nothing here reaches `@mailwoman/core`: the package's build project declares no reference to it in
|
|
20
|
+
* either direction, and a generator is not the reason to reverse that. `import.meta.main` is what
|
|
21
|
+
* `runIfScript` reads anyway, and reading it directly keeps this file inside the package's own
|
|
22
|
+
* dependency graph.
|
|
23
|
+
*/
|
|
24
|
+
import { type CompiledGeographicModel } from "../artifact.ts";
|
|
25
|
+
/**
|
|
26
|
+
* The command that rewrites the committed artifact. Stated once, and quoted by the freshness test's failure message, so
|
|
27
|
+
* a reader who trips it is told what to run rather than left to reconstruct it.
|
|
28
|
+
*/
|
|
29
|
+
export declare const REGENERATE_ARTIFACT_COMMAND = "node packages/geographic-model/scripts/build-artifact.ts && npx oxfmt packages/geographic-model/data/geographic-model.json";
|
|
30
|
+
/**
|
|
31
|
+
* The authoring directory and the artifact it compiles to.
|
|
32
|
+
*
|
|
33
|
+
* Two candidates, because this module runs from two places: `scripts/` in the repository, where `data/` is one level
|
|
34
|
+
* up, and `out/scripts/` in a published tarball, where it is two. Probing for the file distinguishes those from a
|
|
35
|
+
* genuinely missing `data/`, which throws with both paths named.
|
|
36
|
+
*/
|
|
37
|
+
export declare function packagedModelPaths(): {
|
|
38
|
+
source: string;
|
|
39
|
+
artifact: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Load the authored records and compile them. Throws with every violation if they do not load, and with every reason if
|
|
43
|
+
* they load but do not compile; nothing partial is returned.
|
|
44
|
+
*/
|
|
45
|
+
export declare function compileAuthoredGeographicModel(): CompiledGeographicModel;
|
|
46
|
+
/**
|
|
47
|
+
* Read the committed artifact. The format version is checked; the records are not re-validated, because they were
|
|
48
|
+
* validated on the way in.
|
|
49
|
+
*/
|
|
50
|
+
export declare function readCompiledGeographicModel(): CompiledGeographicModel;
|
|
51
|
+
//# sourceMappingURL=build-artifact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-artifact.d.ts","sourceRoot":"","sources":["../../scripts/build-artifact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,OAAO,EAAE,KAAK,uBAAuB,EAAwD,MAAM,gBAAgB,CAAA;AAInH;;;GAGG;AACH,eAAO,MAAM,2BAA2B,+HACqF,CAAA;AAE7H;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CASzE;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,IAAI,uBAAuB,CAExE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,uBAAuB,CAOrE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Generator for `data/geographic-model.json` — the committed compiled artifact, built from the
|
|
7
|
+
* authored records under `data/model/`.
|
|
8
|
+
*
|
|
9
|
+
* The build step is the whole of what this file does: load the authoring directory, compile it,
|
|
10
|
+
* serialize the result. Every decision inside those three calls belongs to `../load.ts`,
|
|
11
|
+
* `../compile.ts` and `../artifact.ts`, and none of them is re-made here.
|
|
12
|
+
*
|
|
13
|
+
* **A committed artifact is these bytes run through `oxfmt`.** The repository formatter also formats
|
|
14
|
+
* committed JSON, and it inlines short arrays, which `JSON.stringify` cannot reproduce. So the
|
|
15
|
+
* freshness check in `test/unit/pharmacy-slice.test.ts` compares the PARSED artifact against a fresh
|
|
16
|
+
* compile, and byte equality is asserted between two compiles instead. The same convention holds
|
|
17
|
+
* `taxonomy.json` in `@mailwoman/poi-taxonomy`; its `data/PROVENANCE.md` states it for that table.
|
|
18
|
+
*
|
|
19
|
+
* Nothing here reaches `@mailwoman/core`: the package's build project declares no reference to it in
|
|
20
|
+
* either direction, and a generator is not the reason to reverse that. `import.meta.main` is what
|
|
21
|
+
* `runIfScript` reads anyway, and reading it directly keeps this file inside the package's own
|
|
22
|
+
* dependency graph.
|
|
23
|
+
*/
|
|
24
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
25
|
+
import { resolve } from "node:path";
|
|
26
|
+
import { parseCompiledGeographicModel, serializeCompiledModel } from "../artifact.js";
|
|
27
|
+
import { compileGeographicModel } from "../compile.js";
|
|
28
|
+
import { loadGeographicModelDirectory } from "../load.js";
|
|
29
|
+
/**
|
|
30
|
+
* The command that rewrites the committed artifact. Stated once, and quoted by the freshness test's failure message, so
|
|
31
|
+
* a reader who trips it is told what to run rather than left to reconstruct it.
|
|
32
|
+
*/
|
|
33
|
+
export const REGENERATE_ARTIFACT_COMMAND = "node packages/geographic-model/scripts/build-artifact.ts && npx oxfmt packages/geographic-model/data/geographic-model.json";
|
|
34
|
+
/**
|
|
35
|
+
* The authoring directory and the artifact it compiles to.
|
|
36
|
+
*
|
|
37
|
+
* Two candidates, because this module runs from two places: `scripts/` in the repository, where `data/` is one level
|
|
38
|
+
* up, and `out/scripts/` in a published tarball, where it is two. Probing for the file distinguishes those from a
|
|
39
|
+
* genuinely missing `data/`, which throws with both paths named.
|
|
40
|
+
*/
|
|
41
|
+
export function packagedModelPaths() {
|
|
42
|
+
const candidates = [resolve(import.meta.dirname, "../data"), resolve(import.meta.dirname, "../../data")];
|
|
43
|
+
const found = candidates.find((candidate) => existsSync(resolve(candidate, "model/model.json")));
|
|
44
|
+
if (!found) {
|
|
45
|
+
throw new Error(`geographic-model: could not find data/model — looked in ${candidates.join(", ")}`);
|
|
46
|
+
}
|
|
47
|
+
return { source: resolve(found, "model"), artifact: resolve(found, "geographic-model.json") };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Load the authored records and compile them. Throws with every violation if they do not load, and with every reason if
|
|
51
|
+
* they load but do not compile; nothing partial is returned.
|
|
52
|
+
*/
|
|
53
|
+
export function compileAuthoredGeographicModel() {
|
|
54
|
+
return compileGeographicModel(loadGeographicModelDirectory(packagedModelPaths().source));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Read the committed artifact. The format version is checked; the records are not re-validated, because they were
|
|
58
|
+
* validated on the way in.
|
|
59
|
+
*/
|
|
60
|
+
export function readCompiledGeographicModel() {
|
|
61
|
+
const text = readFileSync(packagedModelPaths().artifact, "utf8");
|
|
62
|
+
// A corrupt committed artifact is a broken build, and the `SyntaxError` names the offset. The package's parse
|
|
63
|
+
// wrappers live in `@mailwoman/core`, which this package deliberately does not depend on.
|
|
64
|
+
// oxlint-disable-next-line no-restricted-properties -- see the note above.
|
|
65
|
+
return parseCompiledGeographicModel(JSON.parse(text));
|
|
66
|
+
}
|
|
67
|
+
function main() {
|
|
68
|
+
const { artifact } = packagedModelPaths();
|
|
69
|
+
const model = compileAuthoredGeographicModel();
|
|
70
|
+
writeFileSync(artifact, serializeCompiledModel(model));
|
|
71
|
+
console.log(`wrote ${artifact}: ${model.concepts.length} concepts, ${model.relations.length} relations, ${model.mappings.length} mappings, ${model.observations.length} observations, ${model.derivedFacts.length} derived facts (model ${model.modelVersion})`);
|
|
72
|
+
}
|
|
73
|
+
// `import.meta.main` is undefined under a Vite/vitest module graph, so importing this module from a test stays
|
|
74
|
+
// side-effect-free and never rewrites the committed artifact.
|
|
75
|
+
if (import.meta.main) {
|
|
76
|
+
main();
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=build-artifact.js.map
|