@cosyte/terminology 0.0.1 → 0.0.4

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/dist/index.d.ts CHANGED
@@ -38,7 +38,7 @@ interface Coding {
38
38
  /**
39
39
  * A concept described by one or more {@link Coding}s plus optional free text — FHIR R4
40
40
  * `CodeableConcept`. Included so the value layer is complete for downstream consumers even though
41
- * Phase 1's {@link ../conceptmap/translate.translate} operates on a single {@link Coding}.
41
+ * {@link ../conceptmap/translate.translate} operates on a single {@link Coding}.
42
42
  *
43
43
  * @example
44
44
  * ```ts
@@ -102,7 +102,7 @@ declare function codeableConcept(init: CodeableConcept): CodeableConcept;
102
102
  *
103
103
  * **Value-free by construction.** A diagnostic carries a stable code plus, at most, a
104
104
  * code + system + version — **never** a surrounding patient identifier or clinical narrative. A
105
- * code *in patient context* can be PHI (roadmap §7), so messages describe *structure* (a resource
105
+ * code *in patient context* can be PHI, so messages describe *structure* (a resource
106
106
  * path, a code system), never echo arbitrary input *values*.
107
107
  *
108
108
  * @packageDocumentation
@@ -177,13 +177,13 @@ declare const DIAGNOSTIC_CODES: {
177
177
  * code system was not supplied, an unresolvable referenced value set, or a `filter` operator the
178
178
  * engine does not implement. Surfaced as a typed outcome that marks the expansion **incomplete**;
179
179
  * the engine **never** fabricates a member and **never** returns a silently-empty "no members"
180
- * answer for a part it could not compute (roadmap §4.4 — a false "not a member" is a clinical error).
180
+ * answer for a part it could not compute (a false "not a member" is a clinical error).
181
181
  */
182
182
  readonly TERM_VALUESET_CANNOT_EXPAND: "TERM_VALUESET_CANNOT_EXPAND";
183
183
  /**
184
184
  * A **pre-computed** `ValueSet.expansion` is **incomplete** — its `total` exceeds the number of
185
- * `contains` entries, or it is flagged too-costly (the VSAC `$expand` >1200-code truncation hazard,
186
- * roadmap §4.4). The engine **never treats a truncated expansion as complete membership**: a code
185
+ * `contains` entries, or it is flagged too-costly (the VSAC `$expand` >1200-code truncation
186
+ * hazard). The engine **never treats a truncated expansion as complete membership**: a code
187
187
  * absent from a truncated expansion is `undetermined`, never a confident "not a member".
188
188
  */
189
189
  readonly TERM_VALUESET_EXPANSION_TRUNCATED: "TERM_VALUESET_EXPANSION_TRUNCATED";
@@ -191,7 +191,7 @@ declare const DIAGNOSTIC_CODES: {
191
191
  * A UCUM unit expression is **not valid** — it does not parse against the UCUM grammar, or it
192
192
  * names an atom absent from the vendored UCUM table. A **first-class typed outcome, never an
193
193
  * error and never a guess**: {@link validateUcum} returns `{ valid: false, reason }`, never a
194
- * coerced or "nearest" unit (the never-fabricate invariant, applied to units — roadmap §4.3). The
194
+ * coerced or "nearest" unit (the never-fabricate invariant, applied to units). The
195
195
  * `reason` is value-free (a grammar fault or an unknown-atom shape), never PHI.
196
196
  */
197
197
  readonly TERM_UCUM_INVALID: "TERM_UCUM_INVALID";
@@ -199,7 +199,7 @@ declare const DIAGNOSTIC_CODES: {
199
199
  * A crosswalk source code has an **authored No-Map** — the steward declares it has no valid target
200
200
  * in the other classification (a GEM `NoDx`/`NoPCS` sentinel, or a SNOMED complex-map `447638001`
201
201
  * "cannot be classified" category). A **first-class typed outcome, never an error and never a
202
- * guess** (the never-fabricate invariant, applied to crosswalks — roadmap §4.1). Distinct from
202
+ * guess** (the never-fabricate invariant, applied to crosswalks). Distinct from
203
203
  * {@link TERM_CROSSWALK_UNMAPPED}: the source *is* in the map, and the map says "no target".
204
204
  */
205
205
  readonly TERM_CROSSWALK_NO_MAP: "TERM_CROSSWALK_NO_MAP";
@@ -213,7 +213,7 @@ declare const DIAGNOSTIC_CODES: {
213
213
  /**
214
214
  * A SNOMED→ICD-10-CM complex-map group's decision needs **patient context** (an `IFA` age band or
215
215
  * gender) the caller did not supply. The engine surfaces the candidate rules + advice and **refuses
216
- * to pick a branch** it lacks the data for (roadmap §4.1) — never a silently-chosen target.
216
+ * to pick a branch** it lacks the data for — never a silently-chosen target.
217
217
  */
218
218
  readonly TERM_CROSSWALK_CONTEXT_REQUIRED: "TERM_CROSSWALK_CONTEXT_REQUIRED";
219
219
  /**
@@ -235,17 +235,27 @@ declare const DIAGNOSTIC_CODES: {
235
235
  * **silently** — they are expected, not faults.
236
236
  */
237
237
  readonly TERM_RXNORM_MALFORMED_ROW: "TERM_RXNORM_MALFORMED_ROW";
238
+ /**
239
+ * An `RXCUI` appeared in the release's `SAB=RXNORM` atoms but **none of them could establish its
240
+ * term type**, so it is **not** in the graph. Either every atom carried a synonym-class `TTY`
241
+ * (`PSN`/`SY`/`TMSY`, which Appendix 5 defines as a "synonym of another TTY" and which therefore
242
+ * types a *name* rather than a concept) or every atom carried a `TTY` this engine does not model.
243
+ * The concept is skipped rather than typed from a synonym atom: an absent concept is already a
244
+ * first-class typed answer (`TERM_RXNORM_UNKNOWN_RXCUI`), while a concept whose term type reads
245
+ * `TMSY` is a fabricated claim about what a drug *is* that a caller cannot detect.
246
+ */
247
+ readonly TERM_RXNORM_UNTYPED_CONCEPT: "TERM_RXNORM_UNTYPED_CONCEPT";
238
248
  /**
239
249
  * A RxNorm graph navigation was asked about an `RXCUI` **absent from the loaded release** — a
240
250
  * first-class typed outcome, never a fabricated concept and never an empty "success" (the
241
- * never-fabricate invariant, applied to the drug graph — roadmap §4.2). Distinct from a *present*
251
+ * never-fabricate invariant, applied to the drug graph). Distinct from a *present*
242
252
  * concept that simply has no edge of the requested relationship (that is a found result with empty
243
253
  * targets).
244
254
  */
245
255
  readonly TERM_RXNORM_UNKNOWN_RXCUI: "TERM_RXNORM_UNKNOWN_RXCUI";
246
256
  /**
247
257
  * An NDC could **not be resolved** to any `RXCUI` in the loaded RxNorm release — a typed, surfaced
248
- * absence, never a guessed `RXCUI`. NDC↔RXCUI is many:1 and temporal (roadmap §4.2), so a resolution
258
+ * absence, never a guessed `RXCUI`. NDC↔RXCUI is many:1 and temporal, so a resolution
249
259
  * is always release-scoped; an NDC not present in the loaded release is this diagnostic.
250
260
  */
251
261
  readonly TERM_RXNORM_NDC_UNMAPPED: "TERM_RXNORM_NDC_UNMAPPED";
@@ -295,7 +305,7 @@ declare const FATAL_CODES: {
295
305
  /**
296
306
  * An **inversion** of a directional crosswalk was requested — a forbidden operation. The GEMs and
297
307
  * the SNOMED→ICD-10-CM map are authoritative in **one direction only**; a forward map is not the
298
- * inverse of the backward map (roadmap §4.1). Thrown by {@link ../crosswalk/gems.invertGem} so the
308
+ * inverse of the backward map. Thrown by {@link ../crosswalk/gems.invertGem} so the
299
309
  * never-invert refusal is a first-class, discoverable contract rather than a silent absence.
300
310
  */
301
311
  readonly TERM_MAP_NOT_INVERTIBLE: "TERM_MAP_NOT_INVERTIBLE";
@@ -342,7 +352,7 @@ declare class TerminologyError extends Error {
342
352
  * is the terminology-engine analogue of a parser's lenient tokenizer — liberal on load.
343
353
  *
344
354
  * These helpers are **value-free**: they read structure, never log or echo field *values*, so a
345
- * code-in-context (which can be PHI, per the roadmap's PHI posture) never flows into a message.
355
+ * code-in-context (which can be PHI) never flows into a message.
346
356
  *
347
357
  * @packageDocumentation
348
358
  */
@@ -427,9 +437,9 @@ declare function getNumber(obj: unknown, key: string): number | undefined;
427
437
  * ecosystem uses.
428
438
  *
429
439
  * A code-system *identity* (the triple of canonical URI, OID, and HL7 v2 mnemonic that all name
430
- * the same terminology) is a **published fact**, not copyrighted content — so it is encoded here,
431
- * cited firsthand. This is the license line the roadmap draws: identities are facts we may encode;
432
- * the code *lists themselves* (SNOMED/CPT/LOINC content) are BYO and never bundled.
440
+ * the same terminology) is a **published identifier** for the system, not the system's code list — so
441
+ * it is encoded here, cited firsthand. That is where the line falls: identities are encoded; the code
442
+ * *lists themselves* (SNOMED CT / CPT / LOINC content) are BYO and never bundled.
433
443
  *
434
444
  * **Every identity below is grounded firsthand against a primary source** (verified 2026-07-21):
435
445
  *
@@ -442,8 +452,8 @@ declare function getNumber(obj: unknown, key: string): number | undefined;
442
452
  * - HL7 Table 0396 (coding-system mnemonics) — the THO `v2-0396` code system — for the mnemonics
443
453
  * (`LN`, `SCT`, `I10C`, `RXNORM`, `UCUM`, `C4`, `NDC`, `CVX`).
444
454
  *
445
- * Identities that could not be pinned to a primary source firsthand this pass are **omitted**, not
446
- * guessed (roadmap: "do not guess an identity") — notably ICD-9-CM and ICD-10-PCS, whose OID
455
+ * Identities that could not be pinned to a primary source firsthand are **omitted**, not
456
+ * guessed — notably ICD-9-CM and ICD-10-PCS, whose OID
447
457
  * assignments were ambiguous across sources.
448
458
  *
449
459
  * @packageDocumentation
@@ -754,15 +764,14 @@ declare function loadConceptMap(json: unknown): ConceptMap;
754
764
  *
755
765
  * Given a source {@link Coding} and a loaded {@link ConceptMap}, it returns the declared target
756
766
  * code(s) with their FHIR relationship and the map's provenance — or, when the source does not map,
757
- * a **typed {@link TranslateUnmapped}**. This slice births the invariants every later phase
758
- * inherits:
767
+ * a **typed {@link TranslateUnmapped}**. Two invariants govern it:
759
768
  *
760
769
  * 1. **Never fabricate.** An unmapped source yields a surfaced `unmapped` result — never a guessed
761
770
  * target. Every target returned is drawn verbatim from the map; the engine invents nothing.
762
771
  * 2. **Never invert.** Translation reads the map in its authored direction only: a source coding is
763
772
  * matched against `group.element.code` (the source side) and **never** against target codes. A
764
773
  * directional map therefore cannot be run backwards — reverse translation requires an explicit
765
- * inverse map (a later phase), it is never synthesized here.
774
+ * inverse map; it is never synthesized here.
766
775
  *
767
776
  * @packageDocumentation
768
777
  */
@@ -804,14 +813,14 @@ declare function loadConceptMap(json: unknown): ConceptMap;
804
813
  declare function translate(sourceCoding: Coding, map: ConceptMap): TranslateResult;
805
814
 
806
815
  /**
807
- * The types for the **CodeSystem load layer** and the FHIR `$lookup` / `$validate-code` operations
808
- * (roadmap Phase 2): the immutable {@link CodeSystem} model, the per-concept {@link ConceptStatus},
816
+ * The types for the **CodeSystem load layer** and the FHIR `$lookup` / `$validate-code`
817
+ * operations: the immutable {@link CodeSystem} model, the per-concept {@link ConceptStatus},
809
818
  * and the discriminated {@link CodeSystemSource} union the loaders accept.
810
819
  *
811
820
  * The model is **content-agnostic**: it is fed a code system's *release* (a consumer-supplied RRF,
812
821
  * CSV, fixed-width file, or FHIR `CodeSystem` JSON) and answers the two identity questions. It ships
813
- * **zero copyrighted content** — every concept comes from the caller's data (roadmap §5, the BYO-data
814
- * posture). The FHIR operation shapes are grounded firsthand on the FHIR R4 Terminology Module
822
+ * **no code-system release** — every concept comes from the caller's data (the BYO-data posture).
823
+ * The FHIR operation shapes are grounded firsthand on the FHIR R4 Terminology Module
815
824
  * (`https://hl7.org/fhir/R4/codesystem-operation-lookup.html`,
816
825
  * `https://hl7.org/fhir/R4/codesystem-operation-validate-code.html`).
817
826
  *
@@ -833,7 +842,7 @@ declare function translate(sourceCoding: Coding, map: ConceptMap): TranslateResu
833
842
  type ConceptActivity = "active" | "deprecated" | "discouraged" | "trial" | "obsolete" | "suppressed" | "header" | "unknown";
834
843
  /**
835
844
  * The status flags a `$lookup`/`$validate-code` carries on a concept — the safety surface that stops
836
- * a non-current or non-billable code from being presented as clean (roadmap §4.4). Present only when
845
+ * a non-current or non-billable code from being presented as clean. Present only when
837
846
  * the loaded release supplied status information; the engine never fabricates a status.
838
847
  */
839
848
  interface ConceptStatus {
@@ -1059,8 +1068,8 @@ interface FixedWidthFieldMap {
1059
1068
  /**
1060
1069
  * A **fixed-width** source (slice by column) — e.g. the ICD-10-CM order file. Fully parameterized:
1061
1070
  * the consumer supplies the field slices (see {@link ICD10CM_ORDER_FILE_FIELDS} for the documented
1062
- * ICD-10-CM preset, which they confirm against their release's README — the byte offsets are a
1063
- * flagged open question in the roadmap). BYO.
1071
+ * ICD-10-CM preset, which they confirm against their release's README, since the byte offsets are
1072
+ * not confirmed against an authoritative machine-readable source). BYO.
1064
1073
  */
1065
1074
  interface FixedWidthSource {
1066
1075
  /** Discriminant. */
@@ -1079,7 +1088,7 @@ interface FixedWidthSource {
1079
1088
  readonly statusMap?: StatusMapper;
1080
1089
  }
1081
1090
  /**
1082
- * A **FHIR R4 `CodeSystem`** JSON source (native, license-clean model). The consumer supplies the
1091
+ * A **FHIR R4 `CodeSystem`** JSON source (native, consumer-supplied model). The consumer supplies the
1083
1092
  * untrusted resource; nested `concept` hierarchies are flattened, and the standard `inactive` /
1084
1093
  * `deprecated` concept properties are read into {@link ConceptStatus}.
1085
1094
  */
@@ -1096,8 +1105,8 @@ type CodeSystemSource = RrfSource | CsvSource | FixedWidthSource | FhirCodeSyste
1096
1105
  * {@link loadCodeSystem} — the single entry point that dispatches a {@link CodeSystemSource} to the
1097
1106
  * right reader (RRF / CSV / fixed-width / FHIR) and assembles the immutable {@link CodeSystem}.
1098
1107
  *
1099
- * The engine is **content-agnostic and license-clean**: it loads a *consumer-supplied* release and
1100
- * ships **zero** copyrighted content (roadmap §5). The loaded model is deep-frozen and keyed by code
1108
+ * The engine is **content-agnostic**: it loads a *consumer-supplied* release and ships
1109
+ * **no code-system release** of its own. The loaded model is deep-frozen and keyed by code
1101
1110
  * for O(1) {@link lookup}/{@link validateCode}.
1102
1111
  *
1103
1112
  * @packageDocumentation
@@ -1148,7 +1157,7 @@ declare function loadCodeSystem(source: CodeSystemSource): CodeSystem;
1148
1157
  * `property` values (*"additional information about the code, including status"*).
1149
1158
  * - `$validate-code` returns `result` (*"True if the concept details supplied are valid"*).
1150
1159
  *
1151
- * Both honor the **never-fabricate invariant** born in Phase 1, now applied to code identity: an
1160
+ * Both honor the **never-fabricate invariant**, applied here to code identity: an
1152
1161
  * unknown code yields a typed `unknown` / `valid: false` — **never** a fabricated display and
1153
1162
  * **never** a guessed `valid: true`. A found-but-non-current concept (deprecated, or an ICD-10-CM
1154
1163
  * header) validates as present **but carries its status flag**, so a caller never treats it as clean.
@@ -1206,7 +1215,7 @@ declare function validateCode(cs: CodeSystem, code: string): ValidateCodeResult;
1206
1215
  * UMLS Reference Manual, `https://www.ncbi.nlm.nih.gov/books/NBK9685/`: *"values … are separated by
1207
1216
  * vertical bars (|)"* and each row ends with *"a vertical bar and line termination"*).
1208
1217
  *
1209
- * **Liberal on load** (roadmap §6): a row too short to reach a configured column, or with an empty
1218
+ * **Liberal on load**: a row too short to reach a configured column, or with an empty
1210
1219
  * code, is **skipped and surfaced** as a `TERM_RRF_MALFORMED_ROW` warning — never kept as a partial
1211
1220
  * concept, never a crash. RRF reserves `|` as the delimiter (fields never contain a literal pipe), so
1212
1221
  * a plain split is exact.
@@ -1223,7 +1232,7 @@ declare function validateCode(cs: CodeSystem, code: string): ValidateCodeResult;
1223
1232
  * ```ts
1224
1233
  * import { parseRrfLine } from "@cosyte/terminology";
1225
1234
  *
1226
- * parseRrfLine("314076|ENG|lisinopril 10 MG|"); // => ["314076", "ENG", "lisinopril 10 MG"]
1235
+ * parseRrfLine("316151|ENG|lisinopril 10 MG|"); // => ["316151", "ENG", "lisinopril 10 MG"]
1227
1236
  * ```
1228
1237
  */
1229
1238
  declare function parseRrfLine(line: string): readonly string[];
@@ -1256,8 +1265,8 @@ declare function parseRrf(source: RrfSource): {
1256
1265
  /**
1257
1266
  * The **RFC-4180 CSV** reader — the one release format that needs real quote handling (LOINC's
1258
1267
  * `Loinc.csv`). Fields may be quoted with `"`; inside a quoted field a literal quote is escaped as
1259
- * `""`, and commas and newlines are data. Hand-rolled, zero-dep (roadmap §1: the CSV surface is small
1260
- * and well-specified enough to hand-roll rather than pull a dependency).
1268
+ * `""`, and commas and newlines are data. Hand-rolled, zero-dep (the CSV surface is small and
1269
+ * well-specified enough to hand-roll rather than pull a dependency).
1261
1270
  *
1262
1271
  * **Liberal on load:** a data row with too few fields to reach a configured column is **skipped and
1263
1272
  * surfaced** as a `TERM_CSV_MALFORMED` warning; an unterminated final quote is surfaced too — never a
@@ -1312,9 +1321,8 @@ declare function parseCsvSource(source: CsvSource): {
1312
1321
  *
1313
1322
  * The documented ICD-10-CM preset is {@link ICD10CM_ORDER_FILE_FIELDS} — the position-15 flag
1314
1323
  * (0-based char index 14) is `1` for a **billable/valid** code and `0` for a **header** (grounded on
1315
- * the CMS/CDC order-file layout). Per the roadmap's flagged open question (§10 #4), a consumer should
1316
- * confirm the exact offsets against their release's README before relying on the preset — which is
1317
- * exactly why the reader takes the slices as a parameter.
1324
+ * the CMS/CDC order-file layout). Confirm the exact offsets against your release's README before
1325
+ * relying on the preset — which is exactly why the reader takes the slices as a parameter.
1318
1326
  *
1319
1327
  * **Liberal on load:** a line too short to contain the code slice, or with an empty code, is skipped
1320
1328
  * and surfaced as a `TERM_FIXED_WIDTH_MALFORMED` warning.
@@ -1345,8 +1353,9 @@ declare function sliceField(line: string, slice: FieldSlice): string;
1345
1353
  * - property `shortDescription` — the 60-char short description.
1346
1354
  *
1347
1355
  * Grounded on the CMS/CDC order-file layout; **verify against your release's README** before relying
1348
- * on the exact offsets (roadmap §10 #4 — the CDC PDF resisted authoritative decode). The reader takes
1349
- * the layout as a parameter precisely so this preset is a starting point, not a hardcoded assumption.
1356
+ * on the exact offsets, which are not confirmed against an authoritative machine-readable source.
1357
+ * The reader takes the layout as a parameter precisely so this preset is a starting point, not a
1358
+ * hardcoded assumption.
1350
1359
  */
1351
1360
  declare const ICD10CM_ORDER_FILE_FIELDS: FixedWidthFieldMap;
1352
1361
  /**
@@ -1372,7 +1381,7 @@ declare function parseFixedWidth(source: FixedWidthSource): {
1372
1381
  };
1373
1382
 
1374
1383
  /**
1375
- * The **FHIR R4 `CodeSystem`** JSON loader — the native, license-clean model. Reads the untrusted
1384
+ * The **FHIR R4 `CodeSystem`** JSON loader — the native, consumer-supplied model. Reads the untrusted
1376
1385
  * resource into the engine's {@link Concept} map, flattening nested `concept` hierarchies and mapping
1377
1386
  * the standard concept properties to {@link ConceptStatus}.
1378
1387
  *
@@ -1418,11 +1427,11 @@ declare function parseFhirCodeSystem(source: FhirCodeSystemSource): {
1418
1427
  /**
1419
1428
  * Status interpretation shared by the loaders — the {@link defaultStatusMapper} that turns a raw
1420
1429
  * steward status token into a normalized {@link ConceptActivity}, and {@link makeStatus} which
1421
- * assembles the frozen {@link ConceptStatus} (attaching the stable diagnostic code for the concerns
1422
- * the roadmap names: deprecated and header-not-billable).
1430
+ * assembles the frozen {@link ConceptStatus} (attaching the stable diagnostic code for the two
1431
+ * concerns it distinguishes: deprecated and header-not-billable).
1423
1432
  *
1424
1433
  * The mapper is deliberately **conservative**: it recognizes only the tokens grounded in the format
1425
- * docs (LOINC `STATUS` lifecycle values, RxNorm/UMLS `SUPPRESS` values — roadmap §4.4/§11), and maps
1434
+ * docs (LOINC `STATUS` lifecycle values and RxNorm/UMLS `SUPPRESS` values), and maps
1426
1435
  * everything else to `unknown` — a non-active state carrying the raw token, **never** a guessed
1427
1436
  * clean-active. Every loader lets the consumer override it for a release with bespoke semantics.
1428
1437
  *
@@ -1450,7 +1459,7 @@ declare const defaultStatusMapper: StatusMapper;
1450
1459
  /**
1451
1460
  * Assemble a frozen {@link ConceptStatus} from a normalized activity, carrying the raw token and (for
1452
1461
  * classification systems) the billable flag, and attaching the stable diagnostic code for the two
1453
- * concerns the roadmap names — `TERM_CONCEPT_DEPRECATED` and `TERM_CONCEPT_HEADER_NOT_BILLABLE`.
1462
+ * concerns it distinguishes — `TERM_CONCEPT_DEPRECATED` and `TERM_CONCEPT_HEADER_NOT_BILLABLE`.
1454
1463
  *
1455
1464
  * @param activity - The normalized activity.
1456
1465
  * @param raw - The verbatim steward token, if any (omitted from the result when empty).
@@ -1466,14 +1475,14 @@ declare const defaultStatusMapper: StatusMapper;
1466
1475
  declare function makeStatus(activity: ConceptActivity, raw?: string, billable?: boolean): ConceptStatus;
1467
1476
 
1468
1477
  /**
1469
- * The types for the **ValueSet binding layer** (roadmap Phase 3): the immutable {@link ValueSet}
1478
+ * The types for the **ValueSet binding layer**: the immutable {@link ValueSet}
1470
1479
  * model, the `compose` component/filter shapes, the {@link ExpansionContext} that supplies the loaded
1471
1480
  * code systems and referenced value sets, and the fail-safe {@link ExpandResult} /
1472
1481
  * {@link ValueSetMembership} outcomes.
1473
1482
  *
1474
- * The model is **content-agnostic and license-clean**: a `ValueSet` names codes by system URI and is
1475
- * expanded over **consumer-supplied** {@link CodeSystem} releases — the engine ships **zero** encoded
1476
- * value-set content (SNOMED/CPT/full-UMLS/VSAC value sets are strictly BYO, roadmap §5). The FHIR
1483
+ * The model is **content-agnostic**: a `ValueSet` names codes by system URI and is expanded over
1484
+ * **consumer-supplied** {@link CodeSystem} releases — the engine ships **zero** encoded value-set
1485
+ * content (SNOMED CT / CPT / LOINC / UMLS / VSAC value sets are strictly BYO). The FHIR
1477
1486
  * operation shapes are grounded firsthand on the FHIR R4 Terminology Module
1478
1487
  * (`https://hl7.org/fhir/R4/valueset.html`, `https://hl7.org/fhir/R4/valueset-operation-expand.html`,
1479
1488
  * `https://hl7.org/fhir/R4/valueset-operation-validate-code.html`).
@@ -1545,8 +1554,8 @@ interface ExpansionContains {
1545
1554
  }
1546
1555
  /**
1547
1556
  * A **pre-computed** `ValueSet.expansion` — a cached membership snapshot, used as-is (extensional).
1548
- * The engine never re-derives it; it only checks whether it is **complete** (roadmap §4.4 — a
1549
- * truncated expansion must never read as full membership).
1557
+ * The engine never re-derives it; it only checks whether it is **complete** (a truncated
1558
+ * expansion must never read as full membership).
1550
1559
  */
1551
1560
  interface ValueSetExpansion {
1552
1561
  /** The server-reported total membership, when present (FHIR `expansion.total`). */
@@ -1581,9 +1590,10 @@ interface ValueSet {
1581
1590
  * {@link CodeSystem} releases (for intensional `filter`/`system` includes) and any referenced
1582
1591
  * {@link ValueSet}s (for `compose.include.valueSet`), each keyed by its **canonical URL**.
1583
1592
  *
1584
- * The engine makes **no network call** and holds no bundled content: everything intensional resolves
1593
+ * The engine makes **no network call** and holds no bundled code-system release: everything
1594
+ * intensional resolves
1585
1595
  * through this map, and a system or value set the caller did not supply becomes a typed
1586
- * {@link DiagnosticCode.TERM_VALUESET_CANNOT_EXPAND}, never a fabricated member (roadmap §2, §4.4).
1596
+ * {@link DiagnosticCode.TERM_VALUESET_CANNOT_EXPAND}, never a fabricated member.
1587
1597
  */
1588
1598
  interface ExpansionContext {
1589
1599
  /** Loaded code-system releases, keyed by canonical URI (e.g. `"http://loinc.org"`). */
@@ -1631,7 +1641,7 @@ interface ValueSetMemberDecided {
1631
1641
  * A **fail-safe undetermined** membership — the never-fabricate outcome for a value set that could
1632
1642
  * not be fully evaluated (a missing code system, a truncated expansion). The engine refuses to guess:
1633
1643
  * it returns neither `true` nor `false`, so a caller can never mistake "we could not check" for "not a
1634
- * member" (roadmap §4.4 — a false "not a member" is a clinical error).
1644
+ * member" (a false "not a member" is a clinical error).
1635
1645
  */
1636
1646
  interface ValueSetMemberUndetermined {
1637
1647
  /** Discriminant: membership could not be decided. */
@@ -1696,7 +1706,7 @@ declare function loadValueSet(json: unknown): ValueSet;
1696
1706
  * `https://hl7.org/fhir/R4/valueset.html#compose`):
1697
1707
  *
1698
1708
  * - A **pre-computed** `expansion` is used as-is (extensional), and its completeness is checked — a
1699
- * truncated snapshot is flagged, never treated as full membership (roadmap §4.4).
1709
+ * truncated snapshot is flagged, never treated as full membership.
1700
1710
  * - An intensional `compose` is expanded over **consumer-supplied** {@link ../codesystem/types.CodeSystem}
1701
1711
  * releases: the union of `include` components minus the union of `exclude` components. Each component
1702
1712
  * selects by explicit `concept`, by `filter` (subsumption + property predicates), by the whole
@@ -1751,8 +1761,8 @@ declare function expand(vs: ValueSet, ctx?: ExpansionContext): ExpandResult;
1751
1761
  * not removed by any computable `exclude` is a definite member; a code absent from a fully-evaluated
1752
1762
  * value set is a definite non-member. When any relevant part cannot be evaluated (a missing code
1753
1763
  * system, a truncated pre-computed expansion, an unimplemented `filter`), the answer is a typed
1754
- * {@link ValueSetMemberUndetermined} — **never** a fabricated `false` (roadmap §4.4: a false "not a
1755
- * member" is a clinical error).
1764
+ * {@link ValueSetMemberUndetermined} — **never** a fabricated `false` (a false "not a member" is a
1765
+ * clinical error).
1756
1766
  *
1757
1767
  * @packageDocumentation
1758
1768
  */
@@ -1786,9 +1796,9 @@ declare function validateCodeInValueSet(coding: Coding, valueSet: ValueSet, ctx?
1786
1796
  * **Subsumption** is read from the loaded {@link CodeSystem}'s **`parent`** concept-properties
1787
1797
  * (`http://hl7.org/fhir/concept-properties#parent`) — which the FHIR loader synthesizes from a nested
1788
1798
  * `concept` hierarchy and carries verbatim from an explicit `parent` property. This is deliberately
1789
- * the release's **own** hierarchy (roadmap: "hierarchy/`$subsumes` minimal; deep subsumption is
1790
- * Phase 5"); a code system that encodes no parent edges has no descendants beyond identity, and that
1791
- * is treated as complete — not guessed deeper.
1799
+ * the release's **own** hierarchy: subsumption across two separate releases is not computed, and a
1800
+ * code system that encodes no parent edges has no descendants beyond identity, which is treated as
1801
+ * complete — not guessed deeper.
1792
1802
  *
1793
1803
  * **Filter support is explicit.** `is-a` / `descendent-of` / `is-not-a` / `=` / `in` / `not-in` /
1794
1804
  * `exists` are implemented; `regex` / `generalizes` / anything unrecognized report `supported: false`
@@ -1886,15 +1896,16 @@ interface FilterMatch {
1886
1896
  declare function matchesFilter(concept: Concept, filter: ConceptSetFilter, sub: Subsumption): FilterMatch;
1887
1897
 
1888
1898
  /**
1889
- * Types for the **UCUM unit layer** (roadmap Phase 4): the parsed unit AST, the reduced
1899
+ * Types for the **UCUM unit layer**: the parsed unit AST, the reduced
1890
1900
  * (canonical) dimensional form, and the public {@link UcumValidation} result.
1891
1901
  *
1892
1902
  * The layer is **recognition + validation + representation canonicalization only** — it answers
1893
1903
  * "is this a valid UCUM expression" and "are these two expressions the same unit", and it
1894
1904
  * canonicalizes a unit's *representation*. It performs **no magnitude conversion** (`mg/dL` →
1895
- * `mmol/L` needs an analyte's molar mass — a clinical computation the engine refuses, roadmap
1896
- * §2/§4.3). The tables are the vendored, verbatim UCUM `ucum-essence.xml` (roadmap §5), transformed
1897
- * to an in-memory model at runtime; the engine ships **no derivative** of the UCUM table.
1905
+ * `mmol/L` needs an analyte's molar mass — a clinical computation the engine refuses). The tables
1906
+ * are the UCUM `ucum-essence.xml`, **bundled verbatim** in this package (copyright © Regenstrief
1907
+ * Institute, Inc. — see `vendor/ucum/NOTICE.md`) and transformed to an in-memory model at runtime;
1908
+ * the engine ships **no derivative** of the UCUM table.
1898
1909
  *
1899
1910
  * @packageDocumentation
1900
1911
  */
@@ -2039,11 +2050,11 @@ type UcumValidation = {
2039
2050
  };
2040
2051
 
2041
2052
  /**
2042
- * The public **UCUM** surface (roadmap Phase 4): {@link validateUcum} (recognition + a canonical
2053
+ * The public **UCUM** surface: {@link validateUcum} (recognition + a canonical
2043
2054
  * descriptor) and {@link ucumEqual} (are two expressions the *same unit*).
2044
2055
  *
2045
2056
  * Both are **recognition / validation / representation-canonicalization only** — never magnitude
2046
- * conversion (roadmap §2/§4.3). The never-fabricate posture holds: an unparseable or unknown unit is
2057
+ * conversion. The never-fabricate posture holds: an unparseable or unknown unit is
2047
2058
  * a typed {@link TERM_UCUM_INVALID} outcome carrying a value-free reason, **never** a guessed
2048
2059
  * "nearest" unit; and a special (non-linear) unit is never claimed equal to a linear one.
2049
2060
  *
@@ -2094,7 +2105,7 @@ declare function validateUcum(unit: string): UcumValidation;
2094
2105
  declare function ucumEqual(a: string, b: string): boolean;
2095
2106
 
2096
2107
  /**
2097
- * The **UCUM grammar parser** (roadmap Phase 4): a hand-rolled, zero-dependency recursive-descent
2108
+ * The **UCUM grammar parser**: a hand-rolled, zero-dependency recursive-descent
2098
2109
  * parser from a unit expression string to a {@link UnitNode} AST, grounded firsthand on the UCUM
2099
2110
  * specification's syntax (base units, metric prefixes attached with no delimiter and resolved by
2100
2111
  * longest-match, `.` multiply / `/` divide, signed integer exponents, `{…}` inert annotations, and
@@ -2131,13 +2142,13 @@ interface ParseFailure {
2131
2142
  declare function parseUcum(unit: string): ParseResult;
2132
2143
 
2133
2144
  /**
2134
- * **Dimensional reduction** of a parsed UCUM unit (roadmap Phase 4): reduce an expression to its
2145
+ * **Dimensional reduction** of a parsed UCUM unit: reduce an expression to its
2135
2146
  * canonical base-unit form — a scalar factor times a map of the seven UCUM base dimensions
2136
2147
  * (`m s g rad K C cd`), recursively substituting each atom's essence definition down to base units.
2137
2148
  *
2138
2149
  * This is **representation** canonicalization, not magnitude *conversion*: it answers "are these two
2139
2150
  * expressions the same unit" (`N` ≡ `kg.m/s2`, `mmol/L` ≡ `mmol.L-1`), never "what is 5 mg/dL in
2140
- * mmol/L" (that needs an analyte's molar mass — refused, roadmap §2/§4.3). **Special** units (`Cel`,
2151
+ * mmol/L" (that needs an analyte's molar mass, which the engine refuses). **Special** units (`Cel`,
2141
2152
  * `B`, `[pH]`) are non-linear and carry no factor/dimension — they reduce to an opaque normalized
2142
2153
  * form and are never equated with a linear unit. **Arbitrary** units (`[IU]`, `[arb'U]`) are modeled
2143
2154
  * as their own dimension axis, so they cancel with themselves but convert to nothing else.
@@ -2171,8 +2182,9 @@ declare function reduce(node: UnitNode): Reduction;
2171
2182
  * Hand-rolled, **zero-dependency** scanning of a known-well-formed document (not a general XML
2172
2183
  * parser): the essence file is a flat, regular list of `<prefix>` / `<base-unit>` / `<unit>`
2173
2184
  * elements. Parsed **once**, lazily, and cached — the engine reads no file at runtime; the table is
2174
- * a pure transform of the embedded verbatim content (a permitted UCUM use, not a derivative — see
2175
- * `vendor/ucum/NOTICE.md`).
2185
+ * a pure in-process transform of the embedded verbatim content, never serialized or distributed. The
2186
+ * UCUM table is copyright © Regenstrief Institute, Inc. and is bundled verbatim — see
2187
+ * `vendor/ucum/NOTICE.md`, which ships with this package.
2176
2188
  *
2177
2189
  * @packageDocumentation
2178
2190
  */
@@ -2192,7 +2204,7 @@ declare function reduce(node: UnitNode): Reduction;
2192
2204
  declare function loadUcumEssence(): UcumEssence;
2193
2205
 
2194
2206
  /**
2195
- * The types for the **crosswalk resolvers** (roadmap Phase 5) — the CMS ICD-9↔ICD-10 **GEMs**
2207
+ * The types for the **crosswalk resolvers** — the CMS ICD-9↔ICD-10 **GEMs**
2196
2208
  * (General Equivalence Mappings) and the NLM **SNOMED CT → ICD-10-CM complex map**.
2197
2209
  *
2198
2210
  * Both are the library's highest-risk surface, and their types are built around the stewards' own
@@ -2206,8 +2218,7 @@ declare function loadUcumEssence(): UcumEssence;
2206
2218
  * - a 1:many source yields the **whole** ordered candidate set, never one confident pick;
2207
2219
  * - a context-dependent rule with no runtime context is a typed {@link ComplexMapContextRequired} —
2208
2220
  * the rule + advice ride through, the engine never picks a branch it wasn't given the data for;
2209
- * - all Map Advice / GEM flags ride through **verbatim** ("advice flags must not be swallowed",
2210
- * roadmap §4.1);
2221
+ * - all Map Advice / GEM flags ride through **verbatim** (advice flags must not be swallowed);
2211
2222
  * - a directional map is **never inverted** (see {@link ../crosswalk/gems.invertGem}).
2212
2223
  *
2213
2224
  * @packageDocumentation
@@ -2216,7 +2227,7 @@ declare function loadUcumEssence(): UcumEssence;
2216
2227
  /**
2217
2228
  * The **direction** of a loaded GEM file. CMS ships the forward (ICD-9→ICD-10, `…_I9gem.txt`) and
2218
2229
  * backward (ICD-10→ICD-9, `…_I10gem.txt`) maps as **separate, non-inverse artifacts** — a forward map
2219
- * composed with a backward map is *"not a mirror image"* (roadmap §4.1). A `GemMap` therefore records
2230
+ * composed with a backward map is *"not a mirror image"*. A `GemMap` therefore records
2220
2231
  * which direction it is and is only ever applied in that direction.
2221
2232
  */
2222
2233
  type GemDirection = "9-to-10" | "10-to-9";
@@ -2236,7 +2247,7 @@ interface GemFlags {
2236
2247
  /**
2237
2248
  * Position 2 — **no-map** flag. `true` when the source code has **no valid target** in the other
2238
2249
  * classification (the target field is the `NoDx`/`NoPCS` sentinel). A first-class typed outcome —
2239
- * surfaced as a {@link CrosswalkNoMap}, never a fabricated target (roadmap §4.1).
2250
+ * surfaced as a {@link CrosswalkNoMap}, never a fabricated target.
2240
2251
  */
2241
2252
  readonly noMap: boolean;
2242
2253
  /**
@@ -2290,7 +2301,7 @@ interface GemMap {
2290
2301
  }
2291
2302
  /**
2292
2303
  * A surfaced, non-fatal GEM load warning — a malformed line that was **skipped**, reported with its
2293
- * line number and a value-free structural reason. Liberal on load (roadmap §6, the parsers' posture).
2304
+ * line number and a value-free structural reason. Liberal on load (the parsers' posture).
2294
2305
  */
2295
2306
  interface GemLoadWarning {
2296
2307
  /** The stable diagnostic code for a skipped GEM row. */
@@ -2336,8 +2347,8 @@ interface GemMatched {
2336
2347
  }
2337
2348
  /**
2338
2349
  * One row of the SNOMED CT → ICD-10-CM **complex/extended map** refset — the caller-supplied,
2339
- * SNOMED-licensed content the resolver runs over (**no SNOMED content is bundled**; roadmap §5). The
2340
- * field names paraphrase the SNOMED RF2 extended-map refset columns.
2350
+ * SNOMED-licensed content the resolver runs over (**no SNOMED CT refset is bundled**). The field
2351
+ * names paraphrase the SNOMED RF2 extended-map refset columns.
2341
2352
  */
2342
2353
  interface ComplexMapEntry {
2343
2354
  /** The SNOMED CT source concept id (`referencedComponentId`), verbatim. */
@@ -2361,7 +2372,7 @@ interface ComplexMapEntry {
2361
2372
  /**
2362
2373
  * The **map advice**, verbatim (pipe-delimited in the source) — steward instructions to a human
2363
2374
  * (`CONSIDER LATERALITY`, `EPISODE OF CARE INFORMATION NEEDED`, `THIS IS A MANIFESTATION CODE…`).
2364
- * Carried through untouched: advice flags must **never** be swallowed (roadmap §4.1).
2375
+ * Carried through untouched: advice flags must **never** be swallowed.
2365
2376
  */
2366
2377
  readonly advice: string;
2367
2378
  /** The ICD-10-CM **map target** code, verbatim — **absent** for a No-Map / empty-target row. */
@@ -2397,7 +2408,7 @@ interface ComplexMapLoadWarning {
2397
2408
  /**
2398
2409
  * The **caller-supplied patient context** an `IFA` rule is evaluated against. The resolver evaluates
2399
2410
  * only against what it is given: a rule needing context absent here surfaces as a
2400
- * {@link ComplexMapContextRequired}, never a silently-picked branch (roadmap §4.1).
2411
+ * {@link ComplexMapContextRequired}, never a silently-picked branch.
2401
2412
  */
2402
2413
  interface PatientContext {
2403
2414
  /** The patient's age **in years**, when known (for `IFA … Age …` bands). */
@@ -2445,7 +2456,7 @@ interface ComplexMapGroupNoMap {
2445
2456
  /**
2446
2457
  * A group whose winning path is a **context-dependent** `IFA` rule (or `447639009`/`447640006`
2447
2458
  * category) for which the caller supplied **no** matching context. The engine surfaces the rules +
2448
- * advice and refuses to pick a branch (roadmap §4.1) — the never-fabricate rule for runtime context.
2459
+ * advice and refuses to pick a branch — the never-fabricate rule for runtime context.
2449
2460
  */
2450
2461
  interface ComplexMapContextRequired {
2451
2462
  /** Discriminant. */
@@ -2469,7 +2480,7 @@ interface ComplexMapMatched {
2469
2480
  /**
2470
2481
  * A **No-Map** outcome — the source is present in the map but the steward declares it has no valid
2471
2482
  * target ("cannot be classified with available data"). A first-class typed result, **never** a
2472
- * fabricated target (roadmap §4.1). Distinct from {@link CrosswalkUnmapped} (source absent entirely).
2483
+ * fabricated target. Distinct from {@link CrosswalkUnmapped} (source absent entirely).
2473
2484
  */
2474
2485
  interface CrosswalkNoMap {
2475
2486
  /** Discriminant: the source did not map. */
@@ -2506,7 +2517,7 @@ type GemApplyResult = GemMatched | CrosswalkNoMap | CrosswalkUnmapped;
2506
2517
  type ComplexMapApplyResult = ComplexMapMatched | CrosswalkUnmapped;
2507
2518
 
2508
2519
  /**
2509
- * The CMS **ICD-9 ↔ ICD-10 GEMs** (General Equivalence Mappings) loader + applier (roadmap Phase 5).
2520
+ * The CMS **ICD-9 ↔ ICD-10 GEMs** (General Equivalence Mappings) loader + applier.
2510
2521
  *
2511
2522
  * The GEMs are **CMS/NCHS public-domain** (US-government work) reference mappings between the ICD-9-CM
2512
2523
  * and ICD-10-CM diagnosis classifications. CMS is emphatic about what they are — *"GEMs are not
@@ -2524,8 +2535,7 @@ type ComplexMapApplyResult = ComplexMapMatched | CrosswalkUnmapped;
2524
2535
  * - **Directional, never inverted.** The forward (9→10) and backward (10→9) files are **separate,
2525
2536
  * non-inverse** artifacts; {@link invertGem} refuses to synthesize one from the other.
2526
2537
  *
2527
- * The engine ships **no GEM content**: the caller supplies the public-domain GEM file (BYO — roadmap
2528
- * §2/§5). Bundling the public-domain packs is the separate content-packs phase.
2538
+ * The engine ships **no GEM content**: the caller supplies the public-domain GEM file (BYO).
2529
2539
  *
2530
2540
  * @packageDocumentation
2531
2541
  */
@@ -2549,7 +2559,7 @@ interface GemSource {
2549
2559
  * malformed 5-digit flag) is **skipped and surfaced** as a {@link GemLoadWarning}, never a
2550
2560
  * partially-parsed entry. An unusable *source* is not possible here (an all-malformed file loads to an
2551
2561
  * empty map with warnings) — there is no fatal for GEM load. Ships **no** GEM content: the entries are
2552
- * the caller's public-domain file (roadmap §5).
2562
+ * the caller's public-domain file.
2553
2563
  *
2554
2564
  * @param source - The {@link GemSource} (raw content + direction + version).
2555
2565
  * @returns The immutable {@link GemMap}.
@@ -2593,7 +2603,7 @@ declare function applyGem(map: GemMap, source: string): GemApplyResult;
2593
2603
  *
2594
2604
  * The never-invert invariant made explicit and discoverable: a forward GEM (9→10) is **not** the
2595
2605
  * inverse of the backward GEM (10→9) — CMS ships them as separate artifacts and *"forward and
2596
- * backward mappings are not simply the reverse"* (roadmap §4.1). To resolve the other direction, load
2606
+ * backward mappings are not simply the reverse"*. To resolve the other direction, load
2597
2607
  * the other file with {@link loadGems}; the engine never synthesizes an inverse.
2598
2608
  *
2599
2609
  * @param map - The map an inversion was (incorrectly) requested for.
@@ -2610,10 +2620,13 @@ declare function applyGem(map: GemMap, source: string): GemApplyResult;
2610
2620
  declare function invertGem(map: GemMap): never;
2611
2621
 
2612
2622
  /**
2613
- * The **SNOMED CT → ICD-10-CM complex-map** resolver (roadmap Phase 5) — a rule-based, **BYO**
2614
- * resolver over the caller-supplied complex/extended-map refset. **No SNOMED CT content is bundled**
2615
- * (roadmap §5): the engine ships the rule machinery; the caller supplies the map rows from their own
2616
- * SNOMED-licensed release.
2623
+ * The **SNOMED CT → ICD-10-CM complex-map** resolver — a rule-based, **BYO**
2624
+ * resolver over the caller-supplied complex/extended-map refset. **No SNOMED CT refset or release is
2625
+ * bundled**: the engine ships the rule machinery; the caller supplies the map rows from their own
2626
+ * SNOMED CT release. (Individual SNOMED CT concepts this resolver *names* are bundled: the
2627
+ * map-category concepts a row's `mapCategoryId` refers to — see
2628
+ * {@link ../crosswalk/categories.MAP_CATEGORIES} — and the two gender findings a gender `IFA` rule
2629
+ * is written against.)
2617
2630
  *
2618
2631
  * The map is *"semi-automated"* by the steward's own statement — 1:many, context-dependent, with
2619
2632
  * first-class No-Map states. The resolver honours that:
@@ -2625,7 +2638,7 @@ declare function invertGem(map: GemMap): never;
2625
2638
  * - **Context it wasn't given, it never guesses.** If deciding a group requires an `IFA` predicate
2626
2639
  * (an age band, a gender) the caller left unspecified, the group is a typed
2627
2640
  * {@link ComplexMapContextRequired} carrying the candidate rules + advice — never a silently-picked
2628
- * branch (roadmap §4.1).
2641
+ * branch.
2629
2642
  * - **No-Map is typed.** A `447638001` "cannot be classified" row (or an empty target) is a typed
2630
2643
  * No-Map, never a fabricated code.
2631
2644
  * - **Advice rides through verbatim.** `CONSIDER LATERALITY`, `EPISODE OF CARE INFORMATION NEEDED`,
@@ -2654,8 +2667,8 @@ type ComplexMapInput = {
2654
2667
  *
2655
2668
  * Liberal on load: a structurally unusable RF2 *row* is skipped and surfaced as a warning; only an
2656
2669
  * unusable *source* (empty content, header missing required columns) is a fatal
2657
- * {@link FATAL_CODES.TERM_CROSSWALK_MALFORMED}. Ships **no** SNOMED content — the rows are the
2658
- * caller's, under their own licence (roadmap §5).
2670
+ * {@link FATAL_CODES.TERM_CROSSWALK_MALFORMED}. Ships **no** SNOMED CT release or refset — the rows
2671
+ * are the caller's, under their own licence.
2659
2672
  *
2660
2673
  * @param input - Structured `rows`, or a raw RF2 extended-map refset `content`.
2661
2674
  * @returns The immutable {@link ComplexMap}.
@@ -2710,23 +2723,25 @@ declare const COMPLEX_MAP_SOURCE_SYSTEM = "http://snomed.info/sct";
2710
2723
  /**
2711
2724
  * Steward-defined **map category** and **map-relationship** identifiers the crosswalk resolvers carry
2712
2725
  * through verbatim — the SNOMED CT complex-map `mapCategoryId` concepts and the map-correlation
2713
- * concepts. These are **published SNOMED CT metadata identifiers** (concept ids in the SNOMED CT
2714
- * Model Component module), encoded here as identity facts (like the code-system OID↔URI facts in
2715
- * {@link ../systems/registry}); **no SNOMED CT content is bundled** — a caller still supplies the map
2716
- * refset itself under their own SNOMED licence (roadmap §5, the BYO posture).
2726
+ * concepts. These are SNOMED CT metadata concepts, and **they are bundled**: the four ids below and
2727
+ * their steward descriptions ship inside this package. SNOMED CT is copyright © International Health
2728
+ * Terminology Standards Development Organisation. **No SNOMED CT refset or release is bundled** — a
2729
+ * caller still supplies the map refset itself under their own SNOMED CT licence (the BYO posture).
2717
2730
  *
2718
2731
  * The category on a resolved SNOMED→ICD-10-CM map row is the steward telling the caller *how much to
2719
2732
  * trust the target*: a `447638001` "cannot be classified" row is a **No-Map**, a `447640006`
2720
2733
  * "ambiguous" row must surface its candidates rather than pick one, and a `447639009`
2721
2734
  * "context-dependent" row needs runtime patient context. The resolver never collapses these to a
2722
- * single confident target (roadmap §4.1).
2735
+ * single confident target.
2723
2736
  *
2724
2737
  * @packageDocumentation
2725
2738
  */
2726
2739
  /**
2727
2740
  * The SNOMED CT complex-map **map category** concept ids — the `mapCategoryId` column of the
2728
- * SNOMED→ICD-10-CM extended-map refset. Encoded as published identity facts; carried through a
2729
- * resolution verbatim so a caller sees the steward's own trust signal.
2741
+ * SNOMED→ICD-10-CM extended-map refset. These four SNOMED CT concepts — id and steward description —
2742
+ * are **bundled** in this package (SNOMED CT is copyright © International Health Terminology
2743
+ * Standards Development Organisation); carried through a resolution verbatim so a caller sees the
2744
+ * steward's own trust signal.
2730
2745
  *
2731
2746
  * @example
2732
2747
  * ```ts
@@ -2765,22 +2780,24 @@ declare const ICD10CM_SYSTEM = "http://hl7.org/fhir/sid/icd-10-cm";
2765
2780
  declare const ICD9CM_SYSTEM = "http://hl7.org/fhir/sid/icd-9-cm";
2766
2781
  /**
2767
2782
  * The canonical code-system URI for **SNOMED CT** — the source system of the SNOMED→ICD-10-CM complex
2768
- * map. Recognised by URI only; **no SNOMED CT content is bundled** (roadmap §5).
2783
+ * map. Recognised by URI only; **no SNOMED CT refset or release is bundled**.
2769
2784
  */
2770
2785
  declare const SNOMEDCT_SYSTEM = "http://snomed.info/sct";
2771
2786
 
2772
2787
  /**
2773
- * The types for the **RxNorm drug relationship graph** (roadmap Phase 6) — the ingredient / brand /
2788
+ * The types for the **RxNorm drug relationship graph** — the ingredient / brand /
2774
2789
  * clinical-drug / dose-form graph navigated over a **caller-supplied** RxNorm RRF release.
2775
2790
  *
2776
2791
  * RxNorm is the US NLM's normalized drug nomenclature. Its concepts (`RXCUI`s) are typed by **term
2777
2792
  * type** ({@link TermType}: `IN` ingredient, `SCD` semantic clinical drug, `SBD` semantic branded
2778
2793
  * drug, `BN` brand name, `DF` dose form, …) and wired together by **directed relationships** carried
2779
2794
  * in `RXNREL.RRF` and labeled by a `RELA` (`has_ingredient`, `tradename_of`, `has_dose_form`,
2780
- * `consists_of`, …). The graph these form is the whole point of this phase: resolve an `SCD` to its
2781
- * ingredients, a branded drug to its generic, a drug to its dose form.
2795
+ * `consists_of`, …). The graph these form is the whole point: resolve a drug to its
2796
+ * components and through them to its ingredient, a branded drug to its generic, a drug to its dose
2797
+ * form. Note that the ingredient edge is authored on the component rather than on the `SCD` itself
2798
+ * (see {@link ../rxnorm/navigate.ingredientsOf}).
2782
2799
  *
2783
- * **The direction convention is a documented medication-safety trap** (roadmap §4.2 / §10 Q5), and it
2800
+ * **The direction convention is a documented medication-safety trap**, and it
2784
2801
  * is grounded here firsthand on the NLM RxNorm Technical Documentation (§12.7) and the UMLS Reference
2785
2802
  * Manual: *"the direction of REL — the relationship which the SECOND concept or atom (with … RXCUI2
2786
2803
  * …) HAS TO the FIRST concept or atom (with … RXCUI1 …)."* So every `RXNREL` row `(RXCUI1, …, RELA,
@@ -2791,9 +2808,10 @@ declare const SNOMEDCT_SYSTEM = "http://snomed.info/sct";
2791
2808
  * fabricates** an `RXCUI` or a relationship absent from the loaded data — an absent concept is a typed
2792
2809
  * {@link RxNormUnknown}, an unresolvable NDC a typed {@link NdcUnmapped}, never a guess.
2793
2810
  *
2794
- * **No RxNorm content is bundled** (roadmap §5): the engine ships the graph *machinery*; the caller
2795
- * supplies the RRF release (the public-domain Current Prescribable Content, or the full BYO release).
2796
- * Bundling the public-domain Prescribable pack is the separate content-packs phase (Phase 7).
2811
+ * **No RxNorm release is bundled**: the engine ships the graph *machinery*, and RxNorm's
2812
+ * relationship and term-type *names* (`RELA`, `TERM_TYPES`); the caller
2813
+ * supplies the RRF release (the public-domain Current Prescribable Content, or the full BYO
2814
+ * release).
2797
2815
  *
2798
2816
  * @packageDocumentation
2799
2817
  */
@@ -2802,8 +2820,13 @@ declare const SNOMEDCT_SYSTEM = "http://snomed.info/sct";
2802
2820
  * `RXNCONSO.RRF` `TTY` values relevant to the drug graph, grounded on the NLM RxNorm Technical
2803
2821
  * Documentation (Appendix 5). Carried verbatim on a {@link RxNormConcept}; the engine classifies but
2804
2822
  * never re-labels a concept.
2823
+ *
2824
+ * `PSN` / `SY` / `TMSY` are Appendix 5's **synonym** term types: each labels an alternate *name* on
2825
+ * some other concept rather than a concept of its own, so they are part of this vocabulary but can
2826
+ * never appear as a loaded {@link RxNormConcept.tty}. See
2827
+ * {@link ../rxnorm/tty.isSynonymTermType}.
2805
2828
  */
2806
- type TermType = "IN" | "PIN" | "MIN" | "BN" | "SCDC" | "SBDC" | "SCD" | "SBD" | "SCDG" | "SBDG" | "GPCK" | "BPCK" | "DF" | "DFG" | "PSN" | "SY" | "TMSY" | "ET";
2829
+ type TermType = "IN" | "PIN" | "MIN" | "BN" | "SCDC" | "SBDC" | "SCDF" | "SBDF" | "SCDFP" | "SBDFP" | "SCD" | "SBD" | "SCDG" | "SBDG" | "SCDGP" | "GPCK" | "BPCK" | "DF" | "DFG" | "PSN" | "SY" | "TMSY" | "ET";
2807
2830
  /**
2808
2831
  * One RxNorm concept (`RXCUI`) as loaded from `RXNCONSO.RRF` — its normalized name and term type.
2809
2832
  * Built from the concept's `SAB=RXNORM` atom (the normalized form); the verbatim `RXCUI`, `TTY`, and
@@ -2812,7 +2835,10 @@ type TermType = "IN" | "PIN" | "MIN" | "BN" | "SCDC" | "SBDC" | "SCD" | "SBD" |
2812
2835
  interface RxNormConcept {
2813
2836
  /** The RxNorm concept unique identifier (`RXCUI`), verbatim. */
2814
2837
  readonly rxcui: string;
2815
- /** The concept's term type ({@link TermType}), verbatim from `RXNCONSO.TTY`. */
2838
+ /**
2839
+ * The concept's term type ({@link TermType}), verbatim from the `RXNCONSO.TTY` of a **defining**
2840
+ * atom. Never a synonym-class `TTY` (`PSN`/`SY`/`TMSY`), which types a name rather than a concept.
2841
+ */
2816
2842
  readonly tty: TermType;
2817
2843
  /** The concept's normalized name (`RXNCONSO.STR`), verbatim. */
2818
2844
  readonly name: string;
@@ -2835,7 +2861,7 @@ interface RxNormEdge {
2835
2861
  /**
2836
2862
  * A resolved **NDC → RXCUI** mapping (from an `RXNSAT.RRF` `ATN=NDC` attribute), carrying the
2837
2863
  * temporal {@link NdcStatus} and the **as-of release** it is valid for. NDC↔RXCUI is many:1 and
2838
- * changes across releases (roadmap §4.2), so a resolution is never timeless — the release rides
2864
+ * changes across releases, so a resolution is never timeless — the release rides
2839
2865
  * through on {@link asOf}.
2840
2866
  */
2841
2867
  interface NdcResolution {
@@ -2855,7 +2881,7 @@ interface NdcResolution {
2855
2881
  * / `UNKNOWN`). An NDC found in the loaded release's `RXNSAT` attributes is `active` **as of that
2856
2882
  * release**; `obsolete` / `alien` come from the RxNav NDC-history data (a differential / BYO source,
2857
2883
  * not the base RRF concept files) and are surfaced only when the caller supplies them — the engine
2858
- * **never fabricates** a non-current status (roadmap §4.2).
2884
+ * **never fabricates** a non-current status.
2859
2885
  */
2860
2886
  type NdcStatus = "active" | "obsolete" | "alien" | "unknown";
2861
2887
  /** An NDC that could not be resolved to any `RXCUI` in the loaded release — a typed absence. */
@@ -2886,8 +2912,8 @@ interface RxNormRelated {
2886
2912
  }
2887
2913
  /**
2888
2914
  * A typed **unknown** navigation result — the queried `RXCUI` is **absent from the loaded graph**. A
2889
- * first-class outcome, never a fabricated concept or an empty success (the never-fabricate invariant,
2890
- * applied to the drug graph — roadmap §4.2). Distinct from a {@link RxNormRelated} with empty
2915
+ * first-class outcome, never a fabricated concept or an empty success (the never-fabricate
2916
+ * invariant, applied to the drug graph). Distinct from a {@link RxNormRelated} with empty
2891
2917
  * `targets`, which means "present, but no such relationship".
2892
2918
  */
2893
2919
  interface RxNormUnknown {
@@ -2901,7 +2927,7 @@ interface RxNormUnknown {
2901
2927
  /** The result of a graph-navigation query: a match (possibly empty) or a typed unknown source. */
2902
2928
  type RxNormNavResult = RxNormRelated | RxNormUnknown;
2903
2929
  /**
2904
- * One **approximate**-match candidate (the opt-in, never-default path — roadmap §4.2). Every field is
2930
+ * One **approximate**-match candidate (the opt-in, never-default path). Every field is
2905
2931
  * marked so a caller can never mistake it for an exact identity: {@link approximate} is always `true`
2906
2932
  * and {@link score} is the labeled, derived similarity. The concept itself is drawn verbatim from the
2907
2933
  * loaded release.
@@ -2915,13 +2941,17 @@ interface RxNormApproximateMatch {
2915
2941
  readonly score: number;
2916
2942
  }
2917
2943
  /**
2918
- * A surfaced, non-fatal RxNorm load warning — a malformed `RXNCONSO` / `RXNREL` / `RXNSAT` row that
2919
- * was **skipped**, reported with its line number and a value-free structural reason (liberal on load,
2920
- * roadmap §6). Never echoes a field value.
2944
+ * A surfaced, non-fatal RxNorm load warning: an `RXNCONSO` / `RXNREL` / `RXNSAT` row (or, for
2945
+ * `TERM_RXNORM_UNTYPED_CONCEPT`, an `RXCUI`) that was **skipped**, reported with its line number and
2946
+ * a value-free structural reason (liberal on load). Never echoes a field value.
2921
2947
  */
2922
2948
  interface RxNormLoadWarning {
2923
- /** The stable diagnostic code for a skipped RxNorm row. */
2924
- readonly code: "TERM_RXNORM_MALFORMED_ROW";
2949
+ /**
2950
+ * The stable diagnostic code for the skip. `TERM_RXNORM_MALFORMED_ROW` is a structurally unusable
2951
+ * row; `TERM_RXNORM_UNTYPED_CONCEPT` is an `RXCUI` no defining atom could type. Both are in the
2952
+ * package-wide {@link ../common/diagnostics.DIAGNOSTIC_CODES} registry, which documents each.
2953
+ */
2954
+ readonly code: "TERM_RXNORM_MALFORMED_ROW" | "TERM_RXNORM_UNTYPED_CONCEPT";
2925
2955
  /** Which source file the fault was in. */
2926
2956
  readonly file: "RXNCONSO" | "RXNREL" | "RXNSAT";
2927
2957
  /** The 1-based source line the fault was found on. */
@@ -2954,7 +2984,7 @@ interface RxNormGraph {
2954
2984
  }
2955
2985
 
2956
2986
  /**
2957
- * The **RxNorm drug graph loader** (roadmap Phase 6) — build an immutable {@link RxNormGraph} from a
2987
+ * The **RxNorm drug graph loader** — build an immutable {@link RxNormGraph} from a
2958
2988
  * **caller-supplied** RxNorm RRF release (`RXNCONSO.RRF` + `RXNREL.RRF`, and optionally `RXNSAT.RRF`
2959
2989
  * for NDC attributes). Reuses the shared, zero-dep {@link ../codesystem/rrf.parseRrfLine} (pipe split,
2960
2990
  * reserved trailing pipe) — the same RRF reader the CodeSystem layer uses.
@@ -2963,8 +2993,8 @@ interface RxNormGraph {
2963
2993
  * descriptions):
2964
2994
  * - `RXNCONSO.RRF` (18 cols): `RXCUI`(0) `LAT`(1) `TS`(2) `LUI`(3) `STT`(4) `SUI`(5) `ISPREF`(6)
2965
2995
  * `RXAUI`(7) `SAUI`(8) `SCUI`(9) `SDUI`(10) `SAB`(11) `TTY`(12) `CODE`(13) `STR`(14) `SRL`(15)
2966
- * `SUPPRESS`(16) `CVF`(17). Only the **normalized** atoms (`SAB=RXNORM`) with a drug-graph `TTY`
2967
- * become graph concepts; the first such atom per `RXCUI` wins.
2996
+ * `SUPPRESS`(16) `CVF`(17). Only the **normalized** atoms (`SAB=RXNORM`) become graph concepts, and
2997
+ * only through a **defining** `TTY` (see "Typing a concept" below).
2968
2998
  * - `RXNREL.RRF` (16 cols): `RXCUI1`(0) `RXAUI1`(1) `STYPE1`(2) `REL`(3) `RXCUI2`(4) `RXAUI2`(5)
2969
2999
  * `STYPE2`(6) `RELA`(7) `RUI`(8) `SRUI`(9) `SAB`(10) `SL`(11) `RG`(12) `DIR`(13) `SUPPRESS`(14)
2970
3000
  * `CVF`(15). Read `subject = RXCUI2`, `predicate = RELA`, `object = RXCUI1` (the direction
@@ -2973,18 +3003,30 @@ interface RxNormGraph {
2973
3003
  * - `RXNSAT.RRF` (13 cols): `RXCUI`(0) … `ATN`(8) `SAB`(9) `ATV`(10) `SUPPRESS`(11) `CVF`(12). Rows
2974
3004
  * with `ATN=NDC` index `ATV`(the NDC) → `RXCUI`, marked `active` **as of** the loaded release.
2975
3005
  *
2976
- * **Liberal on load** (roadmap §6): a structurally unusable *row* (too few columns, missing a required
3006
+ * **Typing a concept (`RXNCONSO`).** An `RXCUI` carries one **defining** atom (its normalized
3007
+ * name, a `TTY` from Appendix 5's "Normalized Names" table) plus any number of **synonym** atoms, whose
3008
+ * `TTY` (`PSN`/`SY`/`TMSY`) Appendix 5 defines as a *"synonym of another TTY"*: it types a **name**,
3009
+ * not a concept. RxNorm documents no ordering between an `RXCUI`'s atoms, so the loader takes the
3010
+ * **defining** atom wherever it sits in the file (first-wins among defining atoms) and **never** falls
3011
+ * back to a synonym atom. An `RXCUI` that no defining atom could type, because every atom is
3012
+ * synonym-class or carries a `TTY` this engine does not model, is **skipped and surfaced** as a
3013
+ * `TERM_RXNORM_UNTYPED_CONCEPT` warning naming the line. Skipping is the deliberate choice: an absent
3014
+ * concept is already a first-class typed outcome (`TERM_RXNORM_UNKNOWN_RXCUI`), whereas a concept
3015
+ * whose `tty` reads `"TMSY"` is a fabricated claim about what the drug *is*, indistinguishable from a
3016
+ * real one.
3017
+ *
3018
+ * **Liberal on load**: a structurally unusable *row* (too few columns, missing a required
2977
3019
  * value) is **skipped and surfaced** as a `TERM_RXNORM_MALFORMED_ROW` warning, never a partial
2978
3020
  * concept/edge, never a crash. Rows that are simply *not of interest* (a non-`RXNORM` atom, an
2979
3021
  * atom-level relationship, a non-`NDC` attribute) are skipped **silently** — they are expected, not
2980
- * faults. Ships **no** RxNorm content: every concept/edge is the caller's release (roadmap §5).
3022
+ * faults. Ships **no** RxNorm release: every concept/edge is the caller's.
2981
3023
  *
2982
3024
  * @packageDocumentation
2983
3025
  */
2984
3026
 
2985
3027
  /**
2986
3028
  * A raw RxNorm RRF release, BYO. The caller supplies the public-domain Current Prescribable Content
2987
- * subset or the full (licensed) release; the engine bundles **no** RxNorm content (roadmap §5).
3029
+ * subset or the full (licensed) release; the engine bundles **no** RxNorm release.
2988
3030
  */
2989
3031
  interface RxNormGraphSource {
2990
3032
  /** The raw `RXNCONSO.RRF` content (pipe-delimited concept/atom names). */
@@ -3001,8 +3043,12 @@ interface RxNormGraphSource {
3001
3043
  *
3002
3044
  * Parses `RXNCONSO` (concepts), `RXNREL` (directed edges, normalized to the documented direction), and
3003
3045
  * — when supplied — `RXNSAT` (NDC attributes). Liberal on load: a structurally unusable row is a
3004
- * skipped, surfaced {@link RxNormLoadWarning}, never partial. Ships **no** RxNorm content — the graph
3005
- * is entirely the caller's release (roadmap §5).
3046
+ * skipped, surfaced {@link RxNormLoadWarning}, never partial. Ships **no** RxNorm release — the graph
3047
+ * is entirely the caller's release.
3048
+ *
3049
+ * A concept is typed only by a **defining** atom, never by a synonym-class one and never by file
3050
+ * order; an `RXCUI` no defining atom could type is skipped and surfaced as
3051
+ * `TERM_RXNORM_UNTYPED_CONCEPT`. See the module documentation.
3006
3052
  *
3007
3053
  * @param source - The {@link RxNormGraphSource} (RRF file contents + optional version).
3008
3054
  * @returns The immutable {@link RxNormGraph}.
@@ -3010,10 +3056,10 @@ interface RxNormGraphSource {
3010
3056
  * ```ts
3011
3057
  * import { loadRxNormGraph } from "@cosyte/terminology";
3012
3058
  *
3013
- * // Synthetic rows in the RxNorm RRF wire format (no real RxNorm content is bundled).
3059
+ * // Synthetic rows in the RxNorm RRF wire format (no RxNorm release is bundled).
3014
3060
  * const graph = loadRxNormGraph({
3015
- * conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||",
3016
- * // "SCD(2) has_ingredient IN(1)": subject=RXCUI2=2, object=RXCUI1=1.
3061
+ * conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCDC||lisinopril 10 MG||N||",
3062
+ * // "SCDC(2) has_ingredient IN(1)": subject=RXCUI2=2, object=RXCUI1=1.
3017
3063
  * rel: "1|||RN|2|||has_ingredient|||RXNORM||||||",
3018
3064
  * });
3019
3065
  * graph.conceptCount; // => 2
@@ -3022,9 +3068,9 @@ interface RxNormGraphSource {
3022
3068
  declare function loadRxNormGraph(source: RxNormGraphSource): RxNormGraph;
3023
3069
 
3024
3070
  /**
3025
- * **RxNorm drug-graph navigation** (roadmap Phase 6) — resolve an `SCD` to its ingredients, a branded
3026
- * drug to its generic, a drug to its dose form, and an NDC to its `RXCUI`, over a loaded
3027
- * {@link RxNormGraph}. Every query is **fail-safe and never-fabricate** (roadmap §4.2):
3071
+ * **RxNorm drug-graph navigation**: resolve a drug to its components and its
3072
+ * ingredient, a branded drug to its generic, a drug to its dose form, and an NDC to its `RXCUI`, over
3073
+ * a loaded {@link RxNormGraph}. Every query is **fail-safe and never-fabricate**:
3028
3074
  *
3029
3075
  * - a queried `RXCUI` absent from the graph is a typed {@link RxNormUnknown}, never a guessed concept;
3030
3076
  * - a present concept with no such relationship is a {@link RxNormRelated} with **empty** `targets` —
@@ -3067,9 +3113,9 @@ declare function getConcept(graph: RxNormGraph, rxcui: string): RxNormConcept |
3067
3113
  * ```ts
3068
3114
  * import { loadRxNormGraph, relatedByRela, RELA } from "@cosyte/terminology";
3069
3115
  *
3070
- * // "SCD(2) has_ingredient IN(1)": subject=RXCUI2=2, object=RXCUI1=1.
3116
+ * // "SCDC(2) has_ingredient IN(1)": subject=RXCUI2=2, object=RXCUI1=1.
3071
3117
  * const g = loadRxNormGraph({
3072
- * conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||",
3118
+ * conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCDC||lisinopril 10 MG||N||",
3073
3119
  * rel: "1|||RN|2|||has_ingredient|||RXNORM||||||",
3074
3120
  * });
3075
3121
  * const r = relatedByRela(g, "2", RELA.HAS_INGREDIENT);
@@ -3081,12 +3127,35 @@ declare function relatedByRela(graph: RxNormGraph, rxcui: string, predicate: str
3081
3127
  * The **ingredients** of a concept — the concepts it links to by a **direct** `has_ingredient` /
3082
3128
  * `has_precise_ingredient` edge in the loaded release.
3083
3129
  *
3084
- * This follows the *authored, direct* edge only (never-fabricate, never a synthesized path). Note the
3085
- * release's own topology: a clinical component (`SCDC`) links directly to its `IN`, whereas some `SCD`
3086
- * releases route the ingredient through the component (`SCD ⟶consists_of⟶ SCDC ⟶has_ingredient⟶ IN`).
3087
- * When a drug's ingredient is not a *direct* edge, this honestly returns found-with-empty-targets —
3088
- * traverse {@link consistsOf} then `ingredientsOf` to reach the ingredient through the component. The
3089
- * engine never invents the transitive edge.
3130
+ * This follows the *authored, direct* edge only (never-fabricate, never a synthesized path), and
3131
+ * **RxNorm's ingredient topology is not the obvious one**. Always read the `TTY` of what comes back:
3132
+ *
3133
+ * - concepts on the **clinical** side (`SCDC`, `SCDF`, `SCDG`) link to the ingredient itself, an
3134
+ * `IN`;
3135
+ * - concepts on the **branded** side (`SBD`, `SBDC`, `SBDF`, `SBDG`) link to their **brand name**, a
3136
+ * `BN`. That is what the release says and what is echoed back, term type included. It is *not* the
3137
+ * active ingredient. (`has_precise_ingredient`, which this function also follows, likewise reaches
3138
+ * a `PIN`.)
3139
+ * - a **clinical drug** (`SCD`) carries **no** `has_ingredient` edge at all. RxNorm authors none, in
3140
+ * any release, so this honestly returns found-with-empty-targets rather than walking a path on the
3141
+ * caller's behalf.
3142
+ * - the **precise** forms (`SCDFP`, `SBDFP`, `SCDGP`) carry **neither** edge, so this returns
3143
+ * found-with-empty-targets for them too. They do **not** behave like their non-precise siblings:
3144
+ * an `SCDFP` reaches its basis-of-strength substance(s) by `has_boss`, a one-to-many relation with
3145
+ * a different meaning whose targets can be a `PIN` or a plain `IN`, and which this function
3146
+ * deliberately does not follow; an `SBDFP` and an
3147
+ * `SCDGP` author no ingredient-bearing edge at all and are reached instead through `form_of` /
3148
+ * `tradename_of` / `isa`.
3149
+ *
3150
+ * Those pairings are the ones RxNorm authors, not a closed set a caller may rely on: check the
3151
+ * returned `TTY` rather than assuming it from the one you queried.
3152
+ *
3153
+ * **To reach an active ingredient, walk to the CLINICAL component and take its edge.** From an `SCD`
3154
+ * that is `SCD ⟶consists_of⟶ SCDC ⟶has_ingredient⟶ IN`, i.e. {@link consistsOf} then
3155
+ * `ingredientsOf`. From an `SBD` it needs one more decision, because `consists_of` returns **both**
3156
+ * its branded component (`SBDC`, whose own ingredient edge is the `BN` again) and the clinical
3157
+ * `SCDC`: it is the `SCDC` that leads to the `IN`. The engine never invents the transitive edge and
3158
+ * never picks that branch for you.
3090
3159
  *
3091
3160
  * @param graph - A loaded {@link RxNormGraph}.
3092
3161
  * @param rxcui - The concept (a drug or a clinical/branded component).
@@ -3095,8 +3164,9 @@ declare function relatedByRela(graph: RxNormGraph, rxcui: string, predicate: str
3095
3164
  * ```ts
3096
3165
  * import { loadRxNormGraph, ingredientsOf } from "@cosyte/terminology";
3097
3166
  *
3167
+ * // The ingredient edge is authored on the COMPONENT, not on the clinical drug.
3098
3168
  * const g = loadRxNormGraph({
3099
- * conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||",
3169
+ * conso: "1|ENG||||||||||RXNORM|IN||lisinopril||N||\n2|ENG||||||||||RXNORM|SCDC||lisinopril 10 MG||N||",
3100
3170
  * rel: "1|||RN|2|||has_ingredient|||RXNORM||||||",
3101
3171
  * });
3102
3172
  * ingredientsOf(g, "2").found; // => true
@@ -3116,7 +3186,7 @@ declare function ingredientsOf(graph: RxNormGraph, rxcui: string): RxNormNavResu
3116
3186
  *
3117
3187
  * // "SBD(2) tradename_of SCD(1)": subject=RXCUI2=2, object=RXCUI1=1.
3118
3188
  * const g = loadRxNormGraph({
3119
- * conso: "1|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||\n2|ENG||||||||||RXNORM|SBD||Zestril 10 MG Oral Tablet||N||",
3189
+ * conso: "1|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||\n2|ENG||||||||||RXNORM|SBD||lisinopril 10 MG Oral Tablet [Zestril]||N||",
3120
3190
  * rel: "1|||RN|2|||tradename_of|||RXNORM||||||",
3121
3191
  * });
3122
3192
  * genericFor(g, "2").found; // => true
@@ -3135,7 +3205,7 @@ declare function genericFor(graph: RxNormGraph, rxcui: string): RxNormNavResult;
3135
3205
  * import { loadRxNormGraph, brandsFor } from "@cosyte/terminology";
3136
3206
  *
3137
3207
  * const g = loadRxNormGraph({
3138
- * conso: "1|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||\n2|ENG||||||||||RXNORM|SBD||Zestril 10 MG Oral Tablet||N||",
3208
+ * conso: "1|ENG||||||||||RXNORM|SCD||lisinopril 10 MG Oral Tablet||N||\n2|ENG||||||||||RXNORM|SBD||lisinopril 10 MG Oral Tablet [Zestril]||N||",
3139
3209
  * rel: "2|||RN|1|||has_tradename|||RXNORM||||||",
3140
3210
  * });
3141
3211
  * brandsFor(g, "1").found; // => true
@@ -3180,7 +3250,7 @@ declare function doseFormsOf(graph: RxNormGraph, rxcui: string): RxNormNavResult
3180
3250
  declare function consistsOf(graph: RxNormGraph, rxcui: string): RxNormNavResult;
3181
3251
  /**
3182
3252
  * Resolve an **NDC** (National Drug Code) to its `RXCUI` in the loaded release, carrying the temporal
3183
- * status and the as-of release. NDC↔RXCUI is many:1 and changes across releases (roadmap §4.2), so an
3253
+ * status and the as-of release. NDC↔RXCUI is many:1 and changes across releases, so an
3184
3254
  * NDC present in the release is `active` **as of that release**; an absent NDC is a typed
3185
3255
  * {@link NdcUnmapped}, never a guessed `RXCUI`.
3186
3256
  *
@@ -3210,12 +3280,12 @@ interface ApproximateMatchOptions {
3210
3280
  readonly limit?: number;
3211
3281
  }
3212
3282
  /**
3213
- * **Opt-in, explicitly labeled** approximate name matching (roadmap §4.2) — find loaded concepts whose
3283
+ * **Opt-in, explicitly labeled** approximate name matching — find loaded concepts whose
3214
3284
  * names are token-similar to `query`. This is **never** the default resolution path and its results
3215
3285
  * are **never** an exact code assertion: every candidate is marked `approximate: true` with a derived
3216
3286
  * {@link RxNormApproximateMatch.score}. A caller opts in by calling this function explicitly.
3217
3287
  *
3218
- * Coverage is not correctness (roadmap §4.2): a "no match" is an **empty** array (typed, honest),
3288
+ * Coverage is not correctness: a "no match" is an **empty** array (typed, honest),
3219
3289
  * distinct from a fabricated nearest guess. The engine never promotes an approximate hit to an exact
3220
3290
  * one.
3221
3291
  *
@@ -3240,10 +3310,10 @@ declare function approximateMatch(graph: RxNormGraph, query: string, options?: A
3240
3310
  * The RxNorm **relationship (`RELA`) vocabulary** and the **direction convention** the drug graph is
3241
3311
  * built on — encoded here as published identity facts (like the code-system OID↔URI facts in
3242
3312
  * {@link ../systems/registry}), grounded firsthand on the NLM RxNorm Technical Documentation and the
3243
- * UMLS Reference Manual. **No RxNorm content is bundled** — only the relationship *names* and the
3244
- * *rule* for reading a row's direction (roadmap §5).
3313
+ * UMLS Reference Manual. **No RxNorm release is bundled** — what ships is the relationship *names*
3314
+ * and the *rule* for reading a row's direction.
3245
3315
  *
3246
- * **The direction rule (roadmap §4.2 / §10 Q5 — a documented medication-safety trap).** From the
3316
+ * **The direction rule (a documented medication-safety trap).** From the
3247
3317
  * RxNorm Technical Documentation (§12.7) and the UMLS Reference Manual, verbatim: *"the direction of
3248
3318
  * REL — the relationship which the SECOND concept or atom (with … RXCUI2 …) HAS TO the FIRST concept
3249
3319
  * or atom (with … RXCUI1 …)."* The doc's worked example — a row with `RXCUI1=1155862`, `RELA=isa`,
@@ -3251,10 +3321,21 @@ declare function approximateMatch(graph: RxNormGraph, query: string, options?: A
3251
3321
  *
3252
3322
  * So an `RXNREL.RRF` row is read **`RXCUI2 ⟶RELA⟶ RXCUI1`**, and {@link ../rxnorm/load.loadRxNormGraph}
3253
3323
  * normalizes every row to `subject = RXCUI2`, `predicate = RELA`, `object = RXCUI1`. Concretely, a
3254
- * `has_ingredient` row places the **drug** in `RXCUI2` and the **ingredient** in `RXCUI1` (the drug
3255
- * *has* the ingredient); a `tradename_of` row places the **branded** concept in `RXCUI2` and the
3256
- * **generic** in `RXCUI1` (the brand *is a tradename of* the generic). Getting this backwards is a
3257
- * wrong-medication bug, so the fixtures pin it against the doc's convention.
3324
+ * `has_ingredient` row places the **having** concept in `RXCUI2` and what it *has* in `RXCUI1`; a
3325
+ * `tradename_of` row places the **branded** concept in `RXCUI2` and the **generic** in `RXCUI1` (the
3326
+ * brand *is a tradename of* the generic). Getting this backwards is a wrong-medication bug, so the
3327
+ * fixtures pin it against the doc's convention.
3328
+ *
3329
+ * **Direction is not topology, and the topology is not the obvious one.** Knowing how to read a row
3330
+ * does not tell you which rows exist. RxNorm authors `has_ingredient` from the **clinical** side
3331
+ * (`SCDC`/`SCDF`/`SCDG`) to an `IN`, and from the **branded** side (`SBD`/`SBDC`/`SBDF`/`SBDG`) to a
3332
+ * `BN` rather than to the active ingredient; it authors **no** `SCD ⟶ IN` ingredient edge at all, so
3333
+ * a clinical drug reaches its ingredient only through `consists_of`. The **precise** forms
3334
+ * (`SCDFP`/`SBDFP`/`SCDGP`) carry no `has_ingredient` row either: an `SCDFP` instead reaches its
3335
+ * basis-of-strength substances by `has_boss` (one-to-many, and its targets can be a `PIN` or a plain
3336
+ * `IN`), and the other two author no ingredient-bearing edge at all. Treat those pairings as the
3337
+ * ones RxNorm authors, not as a closed set, and read the `TTY` of what a traversal returns. See
3338
+ * {@link ../rxnorm/navigate.ingredientsOf}.
3258
3339
  *
3259
3340
  * @packageDocumentation
3260
3341
  */
@@ -3272,9 +3353,17 @@ declare function approximateMatch(graph: RxNormGraph, query: string, options?: A
3272
3353
  * ```
3273
3354
  */
3274
3355
  declare const RELA: {
3275
- /** `has_ingredient` — subject (a drug/component) *has ingredient* object (an `IN`/`PIN`). */
3356
+ /**
3357
+ * `has_ingredient`: subject *has ingredient* object. Authored from the clinical side
3358
+ * (`SCDC`/`SCDF`/`SCDG`) to an `IN` and from the branded side (`SBD`/`SBDC`/`SBDF`/`SBDG`) to a
3359
+ * `BN`; RxNorm authors no `SCD ⟶ IN` row.
3360
+ */
3276
3361
  readonly HAS_INGREDIENT: "has_ingredient";
3277
- /** `ingredient_of` — subject (an `IN`/`PIN`) *is an ingredient of* object (a drug/component). */
3362
+ /**
3363
+ * `ingredient_of`: subject *is an ingredient of* object. The authored inverse, so an `IN` reaches
3364
+ * clinical components and dose forms and a `BN` reaches branded concepts (the `SBD` included).
3365
+ * Neither reaches an `SCD`.
3366
+ */
3278
3367
  readonly INGREDIENT_OF: "ingredient_of";
3279
3368
  /** `has_precise_ingredient` — subject *has precise ingredient* object (a `PIN`). */
3280
3369
  readonly HAS_PRECISE_INGREDIENT: "has_precise_ingredient";
@@ -3331,33 +3420,47 @@ declare const RXNORM_SYSTEM = "http://www.nlm.nih.gov/research/umls/rxnorm";
3331
3420
  /**
3332
3421
  * The RxNorm **term-type (`TTY`) vocabulary** relevant to the drug graph — the normal-form ladder and
3333
3422
  * the cross-link kinds — encoded as published identity facts (grounded firsthand on the NLM RxNorm
3334
- * Technical Documentation, Appendix 5). **No RxNorm content is bundled** (roadmap §5): these are the
3423
+ * Technical Documentation, Appendix 5). **No RxNorm release is bundled**: what ships is these
3335
3424
  * *labels*, not the drug list.
3336
3425
  *
3337
3426
  * The RxNorm normal-form graph runs `IN → SCDC → SCD → SBD` (ingredient → clinical-drug component →
3338
3427
  * semantic clinical drug → semantic branded drug), with `BN` (brand name) and `DF` (dose form) as
3339
- * cross-links (roadmap §4.2).
3428
+ * cross-links.
3429
+ *
3430
+ * **Appendix 5 splits these into two kinds, and the split is load-bearing.** A **defining** term type
3431
+ * (its "Normalized Names" table, `IN` … `DFG`) says what an `RXCUI` *is*. A **synonym** term type
3432
+ * (its "Synonyms" table, `PSN` / `SY` / `TMSY`) is Appendix 5's own word for an atom that is a
3433
+ * *"synonym of another TTY"*: it types a **name**, not a concept, so it can never be a concept's term
3434
+ * type. `ET` is in neither table; the appendix describes it only in prose, as "a small number of
3435
+ * concepts with TTY=ET, a term type reserved for entry terms for dose forms". Those are concepts in
3436
+ * their own right rather than synonyms carried on another, so `ET` counts as defining here. See
3437
+ * {@link isSynonymTermType} and {@link ../rxnorm/load.loadRxNormGraph}.
3340
3438
  *
3341
3439
  * @packageDocumentation
3342
3440
  */
3343
3441
 
3344
3442
  /**
3345
- * The drug-graph term types (`RXNCONSO.TTY`), each mapped to its short gloss. Encoded as an identity
3346
- * fact; a concept's `TTY` is carried verbatim on its {@link ../rxnorm/types.RxNormConcept}, never
3347
- * re-labeled.
3443
+ * The drug-graph term types (`RXNCONSO.TTY`), each mapped to its **verbatim Appendix 5 name** (`ET`
3444
+ * excepted: the appendix publishes no Name for it, so the UMLS expansion "Entry Term" is used).
3445
+ * Encoded as an identity fact; a concept's `TTY` is carried verbatim on its
3446
+ * {@link ../rxnorm/types.RxNormConcept}, never re-labeled.
3447
+ *
3448
+ * The keys are the full Appendix 5 vocabulary, defining and synonym alike. Only the **defining** ones
3449
+ * can appear on a loaded concept (see {@link isSynonymTermType}).
3348
3450
  *
3349
3451
  * @example
3350
3452
  * ```ts
3351
3453
  * import { TERM_TYPES } from "@cosyte/terminology";
3352
3454
  *
3353
3455
  * TERM_TYPES.SCD; // => "Semantic Clinical Drug"
3456
+ * TERM_TYPES.SCDF; // => "Semantic Clinical Drug Form"
3354
3457
  * ```
3355
3458
  */
3356
3459
  declare const TERM_TYPES: Readonly<Record<TermType, string>>;
3357
3460
  /**
3358
3461
  * Narrow a raw `RXNCONSO.TTY` string to a known {@link TermType}, or `undefined` when it is not a
3359
- * drug-graph term type this engine models (the concept is then skipped at load, liberal-on-load —
3360
- * never coerced to a wrong type).
3462
+ * drug-graph term type this engine models (the atom is then skipped at load, liberal-on-load, never
3463
+ * coerced to a wrong type).
3361
3464
  *
3362
3465
  * @param tty - The raw `TTY` value from an `RXNCONSO` row.
3363
3466
  * @returns The narrowed {@link TermType}, or `undefined` when unrecognized.
@@ -3370,6 +3473,25 @@ declare const TERM_TYPES: Readonly<Record<TermType, string>>;
3370
3473
  * ```
3371
3474
  */
3372
3475
  declare function asTermType(tty: string): TermType | undefined;
3476
+ /**
3477
+ * Is this term type a **synonym-class** one (`PSN` / `SY` / `TMSY`)?
3478
+ *
3479
+ * Appendix 5 defines each as a *"synonym of another TTY"*: it labels an alternate **name** for a
3480
+ * concept, never the concept's own kind. So a synonym atom can never establish an `RXCUI`'s term
3481
+ * type, and {@link ../rxnorm/load.loadRxNormGraph} will not let one: an `RXCUI` whose release
3482
+ * supplies only synonym atoms is skipped and surfaced, never typed `"TMSY"`.
3483
+ *
3484
+ * @param tty - A {@link TermType}.
3485
+ * @returns `true` for `PSN` / `SY` / `TMSY`; `false` for every defining term type.
3486
+ * @example
3487
+ * ```ts
3488
+ * import { isSynonymTermType } from "@cosyte/terminology";
3489
+ *
3490
+ * isSynonymTermType("TMSY"); // => true
3491
+ * isSynonymTermType("SCDF"); // => false
3492
+ * ```
3493
+ */
3494
+ declare function isSynonymTermType(tty: TermType): boolean;
3373
3495
 
3374
3496
  /**
3375
3497
  * Public entry point for **`@cosyte/terminology`** — a zero-dependency, developer-focused
@@ -3377,28 +3499,30 @@ declare function asTermType(tty: string): TermType | undefined;
3377
3499
  *
3378
3500
  * Unlike its sibling `@cosyte/*` packages, this is **not a wire-format parser**: it mirrors the
3379
3501
  * **FHIR Terminology Module** (`$translate`, `$lookup`, `$validate-code`, `$expand`, …), operating
3380
- * over **consumer-supplied** FHIR resources. It ships the *engine*, never copyrighted terminology
3381
- * *content* (SNOMED/CPT/full-LOINC/UMLS are strictly BYO); code-system *identities* (OID ↔ URI) are
3382
- * published facts, encoded here and cited firsthand.
3502
+ * over **consumer-supplied** FHIR resources. It ships the *engine* and **no code-system release**
3503
+ * (SNOMED CT / CPT / LOINC / UMLS / RxNorm are strictly BYO). It is not content-free: see
3504
+ * **What is bundled** at the end of this note, which includes the UCUM unit table, the code-system
3505
+ * *identities* (OID ↔ URI), the SNOMED CT concepts the crosswalk resolver names and RxNorm's
3506
+ * relationship and term-type names, each with its copyright.
3383
3507
  *
3384
- * **Phase 1** ships exactly the surface `@cosyte/transform` pins:
3508
+ * **Code-system identity and ConceptMap translation:**
3385
3509
  *
3386
3510
  * - {@link resolveSystem} — the code-system identity / canonical-URI resolver (mnemonic | OID → URI).
3387
3511
  * - {@link loadConceptMap} + {@link translate} — the ConceptMap `$translate` engine, with the
3388
3512
  * **never-fabricate / never-invert** invariants: an unmapped source is a typed
3389
3513
  * {@link TranslateUnmapped}, never a guessed target; a directional map is never run backwards.
3390
3514
  *
3391
- * **Phase 2** adds the CodeSystem load layer and the FHIR `$lookup` / `$validate-code` operations:
3515
+ * **The CodeSystem load layer**, with the FHIR `$lookup` / `$validate-code` operations:
3392
3516
  *
3393
3517
  * - {@link loadCodeSystem} — load a **consumer-supplied** release (RRF / CSV / fixed-width / FHIR
3394
- * `CodeSystem` JSON) into an immutable model. Ships the engine, **never** copyrighted content.
3518
+ * `CodeSystem` JSON) into an immutable model. Ships the loader; **no code-system release**.
3395
3519
  * - {@link lookup} — code → display + properties, carrying status (deprecated / header-not-billable).
3396
3520
  * - {@link validateCode} — is a code a valid member of the system, with its status flags.
3397
3521
  *
3398
3522
  * The never-fabricate invariant holds here too: an unknown code is a typed `unknown` / `valid: false`,
3399
3523
  * never a fabricated display or a guessed `valid: true`.
3400
3524
  *
3401
- * **Phase 3** adds the ValueSet binding layer — FHIR `$expand` / `$validate-code` over a `compose`:
3525
+ * **The ValueSet binding layer** — FHIR `$expand` / `$validate-code` over a `compose`:
3402
3526
  *
3403
3527
  * - {@link loadValueSet} — load a **consumer-supplied** FHIR `ValueSet` (intensional `compose` and/or
3404
3528
  * a pre-computed `expansion`) into an immutable model.
@@ -3408,8 +3532,8 @@ declare function asTermType(tty: string): TermType | undefined;
3408
3532
  * - {@link validateCodeInValueSet} — binding membership, returning a **decided** `result` only when
3409
3533
  * proven and a typed `undetermined` otherwise (a truncated expansion never reads as complete).
3410
3534
  *
3411
- * **Phase 4** adds the **UCUM** unit layer — a hand-rolled UCUM grammar parser + validation +
3412
- * representation canonicalization (recognition only, **no** magnitude conversion):
3535
+ * **The UCUM unit layer** — a hand-rolled UCUM grammar parser + validation + representation
3536
+ * canonicalization (recognition only, **no** magnitude conversion):
3413
3537
  *
3414
3538
  * - {@link validateUcum} — is a string a valid UCUM unit; if so, its canonical descriptor. An
3415
3539
  * invalid unit is a typed `TERM_UCUM_INVALID`, never a guessed "nearest" unit.
@@ -3418,25 +3542,25 @@ declare function asTermType(tty: string): TermType | undefined;
3418
3542
  * - {@link parseUcum} / {@link reduce} / {@link loadUcumEssence} — the underlying grammar parser,
3419
3543
  * dimensional reducer, and the in-memory model of the vendored, verbatim UCUM table.
3420
3544
  *
3421
- * **Phase 5** adds the **crosswalk resolvers** — the never-fabricate/never-invert invariant applied
3422
- * to the published, directional reference maps (roadmap §4.1, the safety crown):
3545
+ * **The crosswalk resolvers** — the never-fabricate/never-invert invariant applied to the
3546
+ * published, directional reference maps:
3423
3547
  *
3424
3548
  * - {@link loadGems} + {@link applyGem} — the CMS **ICD-9↔ICD-10 GEMs** (public-domain reference
3425
3549
  * mappings), honoring the steward's Approximate / No-Map / Combination (scenario→choice-list) flags.
3426
3550
  * A No-Map source is a typed {@link CrosswalkNoMap}; a 1:many source returns the full candidate set.
3427
3551
  * - {@link loadComplexMap} + {@link applyComplexMap} — the NLM **SNOMED CT → ICD-10-CM complex map**
3428
- * (BYO, SNOMED-licensed content — **zero bundled**), evaluating Map Group / Priority / `IFA` Rule /
3552
+ * (BYO — **no SNOMED CT refset bundled**), evaluating Map Group / Priority / `IFA` Rule /
3429
3553
  * Advice / Category against caller-supplied {@link PatientContext}; a rule needing context the
3430
3554
  * caller lacks is a typed {@link ComplexMapContextRequired}, never a guessed branch.
3431
3555
  * - {@link invertGem} — the never-invert refusal made a first-class, thrown contract
3432
3556
  * ({@link FATAL_CODES.TERM_MAP_NOT_INVERTIBLE}).
3433
3557
  *
3434
- * **Phase 6** adds the **RxNorm drug relationship graph** — ingredient / brand / clinical-drug /
3435
- * dose-form navigation over a **caller-supplied** RxNorm RRF release (roadmap §4.2):
3558
+ * **The RxNorm drug relationship graph** — ingredient / brand / clinical-drug / dose-form
3559
+ * navigation over a **caller-supplied** RxNorm RRF release:
3436
3560
  *
3437
3561
  * - {@link loadRxNormGraph} — load `RXNCONSO` (concepts, typed by `TTY`), `RXNREL` (directed `RELA`
3438
3562
  * edges, normalized to the documented `RXCUI2 ⟶RELA⟶ RXCUI1` direction), and optionally `RXNSAT`
3439
- * (NDC attributes) into an immutable graph. Ships **no** RxNorm content — BYO release (roadmap §5).
3563
+ * (NDC attributes) into an immutable graph. Ships **no** RxNorm release — BYO.
3440
3564
  * - {@link ingredientsOf} / {@link genericFor} / {@link brandsFor} / {@link doseFormsOf} /
3441
3565
  * {@link consistsOf} / {@link relatedByRela} — graph navigation following **authored** edges only
3442
3566
  * (the engine never synthesizes an inverse). An absent `RXCUI` is a typed {@link RxNormUnknown}.
@@ -3445,15 +3569,51 @@ declare function asTermType(tty: string): TermType | undefined;
3445
3569
  * - {@link approximateMatch} — the **opt-in, explicitly labeled** similarity path (never the default,
3446
3570
  * never an exact code assertion).
3447
3571
  *
3448
- * Deferred to later phases: the bundleable public-domain content packs, including the RxNorm Current
3449
- * Prescribable Content pack and a GEM pack (the content-packs phase, Phase 7). The GEMs and the
3450
- * Prescribable subset are public-domain, so a caller may supply them today (BYO); SNOMED/CPT/full-UMLS
3451
- * content stays BYO permanently (a licensing wall — roadmap §5).
3572
+ * **What is bundled.** No code-system release is. What is bundled includes the following, named with
3573
+ * its copyright:
3574
+ *
3575
+ * - the **UCUM unit table** (`ucum-essence.xml`, version 2.2, revision-date 2024-06-17) — copyright
3576
+ * ©1999–2024 Regenstrief Institute, Inc., all rights reserved, reproduced **verbatim** under the
3577
+ * UCUM Copyright Notice and License (https://ucum.org/license), embedded byte-for-byte in the
3578
+ * published build and parsed at runtime; no modified or derivative copy is distributed. The UCUM
3579
+ * Specification is provided "as is" **without warranty of any kind** — see the License for the
3580
+ * full disclaimer. The complete notice ships with this package at `vendor/ucum/NOTICE.md`.
3581
+ * - the **code-system identity facts** ({@link SYSTEM_IDENTITIES}) — OID ↔ canonical-URI pairings,
3582
+ * which identify the systems rather than listing any system's codes.
3583
+ * - the **SNOMED CT concepts the crosswalk resolver names**, each with its description: the four
3584
+ * map-category concepts ({@link MAP_CATEGORIES}) a complex-map row's `mapCategoryId` refers to, and
3585
+ * the two gender findings (`248152002` Female, `248153007` Male) a gender `IFA` rule is written
3586
+ * against. Further SNOMED CT identifiers, and ICD-10-CM codes, appear in the API documentation
3587
+ * examples, which are distributed in the compiled declaration files and in the build's
3588
+ * sourcemaps. SNOMED CT is copyright © International Health Terminology Standards
3589
+ * Development Organisation.
3590
+ * - the **RxNorm relationship and term-type names** the drug-graph API is written against: the
3591
+ * relationship names in {@link RELA} / {@link RELA_INVERSE} (`has_ingredient`, `tradename_of`, …),
3592
+ * and the term-type codes in {@link TERM_TYPES}, each with its name as published by the U.S.
3593
+ * National Library of Medicine (`SCD` reads "Semantic Clinical Drug"). Individual RxNorm
3594
+ * identifiers also appear in the API documentation examples, with their RxNorm names and term
3595
+ * types (for instance `RXCUI` `316151`, "lisinopril 10 MG"), and in `README.md` as well as the
3596
+ * places named above. RxNorm is produced by the National Library of Medicine; no RxNorm release
3597
+ * is bundled.
3598
+ *
3599
+ * The `LICENSE` file that ships with this package carries the MIT text for the package's own code
3600
+ * and a third-party notices section naming each of the above.
3601
+ *
3602
+ * The content packs that would change this (the CMS GEM files, the RxNorm Current Prescribable
3603
+ * subset) are not bundled; a caller supplies them, as they do a SNOMED CT, CPT, LOINC, UMLS or VSAC
3604
+ * release, under whatever terms its steward sets. This states what is distributed and under whose
3605
+ * copyright; it is not legal advice, and makes no claim about whether a particular use is permitted
3606
+ * to you.
3452
3607
  *
3453
3608
  * @packageDocumentation
3454
3609
  */
3455
3610
  /**
3456
- * Library version string, synced with `package.json#version` at release time.
3611
+ * Library version string, kept in lockstep with `package.json#version`.
3612
+ *
3613
+ * Changesets owns the bump and rewrites `package.json` only, so the release `version` script runs
3614
+ * `scripts/sync-version.mjs` to rewrite this declaration in the same commit, and
3615
+ * `test/sanity.test.ts` compares the two so a skipped sync goes red instead of shipping a version
3616
+ * string that lies. That is not hypothetical: `0.0.1` went to the registry exporting `"0.0.0"`.
3457
3617
  *
3458
3618
  * @example
3459
3619
  * ```ts
@@ -3461,6 +3621,6 @@ declare function asTermType(tty: string): TermType | undefined;
3461
3621
  * typeof VERSION; // => "string"
3462
3622
  * ```
3463
3623
  */
3464
- declare const VERSION = "0.0.0";
3624
+ declare const VERSION: string;
3465
3625
 
3466
- export { type AnnotationNode, type ApproximateMatchOptions, type BillableFlag, COMPLEX_MAP_SOURCE_SYSTEM, type CodeSystem, type CodeSystemSource, type CodeableConcept, type Coding, type ComplexMap, type ComplexMapApplyResult, type ComplexMapContextRequired, type ComplexMapEntry, type ComplexMapGroupNoMap, type ComplexMapGroupResolved, type ComplexMapGroupResult, type ComplexMapInput, type ComplexMapLoadWarning, type ComplexMapMatched, type ComponentNode, type Concept, type ConceptActivity, type ConceptMap, type ConceptMapElement, type ConceptMapGroup, type ConceptMapTarget, type ConceptMapUnmapped, type ConceptRef, type ConceptSetComponent, type ConceptSetFilter, type ConceptStatus, type CrosswalkNoMap, type CrosswalkUnmapped, type CsvColumnMap, type CsvSource, DIAGNOSTIC_CODES, type DiagnosticCode, type ExpandResult, type ExpansionContains, type ExpansionContext, type ExpansionDiagnostic, FATAL_CODES, type FactorNode, type FatalCode, type FhirCodeSystemSource, type FieldSlice, type FilterMatch, type FilterOperator, type FixedWidthFieldMap, type FixedWidthPropertyField, type FixedWidthSource, type GemApplyResult, type GemChoiceList, type GemDirection, type GemEntry, type GemFlags, type GemLoadWarning, type GemMap, type GemMatched, type GemScenario, type GemSource, type GroupNode, HL7_V2_OID_ROOT, HL7_V2_URL_PREFIX, ICD10CM_ORDER_FILE_FIELDS, ICD10CM_SYSTEM, ICD9CM_SYSTEM, type LinearReduction, type LoadWarning, type LookupOutcome, type LookupResult, type LookupUnknown, MAP_CATEGORIES, type MapCategoryId, type MapProvenance, NO_MAP_CATEGORIES, type NdcResolution, type NdcResult, type NdcStatus, type NdcUnmapped, type ParseFailure, type ParseResult, type PatientContext, type Property, type R4Equivalence, RELA, RELA_INVERSE, RXNORM_SYSTEM, type Reduction, type RelaName, type Relationship, type ResolveSystemResult, type RrfColumnMap, type RrfPropertyColumn, type RrfSource, type RxNormApproximateMatch, type RxNormConcept, type RxNormEdge, type RxNormGraph, type RxNormGraphSource, type RxNormLoadWarning, type RxNormNavResult, type RxNormRelated, type RxNormUnknown, SNOMEDCT_SYSTEM, SYSTEM_IDENTITIES, type SimpleUnitNode, type SpecialReduction, type StatusMapper, type Subsumption, type SystemIdentity, TERM_TYPES, type TermType, TerminologyError, type TranslateMatch, type TranslateMatched, type TranslateResult, type TranslateUnmapped, type UcumAtom, type UcumEssence, type UcumPrefix, type UcumValidation, type UnitNode, type UnknownSystem, type UnmappedMode, VERSION, type ValidateCodeResult, type ValueSet, type ValueSetCompose, type ValueSetExpansion, type ValueSetMemberDecided, type ValueSetMemberUndetermined, type ValueSetMembership, applyComplexMap, applyGem, approximateMatch, asTermType, brandsFor, buildSubsumption, codeableConcept, coding, consistsOf, defaultStatusMapper, doseFormsOf, expand, genericFor, getArray, getBoolean, getConcept, getNumber, getString, ingredientsOf, invertGem, isA, isJsonObject, isUnknownSystem, loadCodeSystem, loadComplexMap, loadConceptMap, loadGems, loadRxNormGraph, loadUcumEssence, loadValueSet, lookup, makeStatus, matchesFilter, parseCsv, parseCsvSource, parseFhirCodeSystem, parseFixedWidth, parseRrf, parseRrfLine, parseUcum, reduce, relatedByRela, resolveNdc, resolveSystem, sliceField, translate, ucumEqual, unsupportedOps, validateCode, validateCodeInValueSet, validateUcum };
3626
+ export { type AnnotationNode, type ApproximateMatchOptions, type BillableFlag, COMPLEX_MAP_SOURCE_SYSTEM, type CodeSystem, type CodeSystemSource, type CodeableConcept, type Coding, type ComplexMap, type ComplexMapApplyResult, type ComplexMapContextRequired, type ComplexMapEntry, type ComplexMapGroupNoMap, type ComplexMapGroupResolved, type ComplexMapGroupResult, type ComplexMapInput, type ComplexMapLoadWarning, type ComplexMapMatched, type ComponentNode, type Concept, type ConceptActivity, type ConceptMap, type ConceptMapElement, type ConceptMapGroup, type ConceptMapTarget, type ConceptMapUnmapped, type ConceptRef, type ConceptSetComponent, type ConceptSetFilter, type ConceptStatus, type CrosswalkNoMap, type CrosswalkUnmapped, type CsvColumnMap, type CsvSource, DIAGNOSTIC_CODES, type DiagnosticCode, type ExpandResult, type ExpansionContains, type ExpansionContext, type ExpansionDiagnostic, FATAL_CODES, type FactorNode, type FatalCode, type FhirCodeSystemSource, type FieldSlice, type FilterMatch, type FilterOperator, type FixedWidthFieldMap, type FixedWidthPropertyField, type FixedWidthSource, type GemApplyResult, type GemChoiceList, type GemDirection, type GemEntry, type GemFlags, type GemLoadWarning, type GemMap, type GemMatched, type GemScenario, type GemSource, type GroupNode, HL7_V2_OID_ROOT, HL7_V2_URL_PREFIX, ICD10CM_ORDER_FILE_FIELDS, ICD10CM_SYSTEM, ICD9CM_SYSTEM, type LinearReduction, type LoadWarning, type LookupOutcome, type LookupResult, type LookupUnknown, MAP_CATEGORIES, type MapCategoryId, type MapProvenance, NO_MAP_CATEGORIES, type NdcResolution, type NdcResult, type NdcStatus, type NdcUnmapped, type ParseFailure, type ParseResult, type PatientContext, type Property, type R4Equivalence, RELA, RELA_INVERSE, RXNORM_SYSTEM, type Reduction, type RelaName, type Relationship, type ResolveSystemResult, type RrfColumnMap, type RrfPropertyColumn, type RrfSource, type RxNormApproximateMatch, type RxNormConcept, type RxNormEdge, type RxNormGraph, type RxNormGraphSource, type RxNormLoadWarning, type RxNormNavResult, type RxNormRelated, type RxNormUnknown, SNOMEDCT_SYSTEM, SYSTEM_IDENTITIES, type SimpleUnitNode, type SpecialReduction, type StatusMapper, type Subsumption, type SystemIdentity, TERM_TYPES, type TermType, TerminologyError, type TranslateMatch, type TranslateMatched, type TranslateResult, type TranslateUnmapped, type UcumAtom, type UcumEssence, type UcumPrefix, type UcumValidation, type UnitNode, type UnknownSystem, type UnmappedMode, VERSION, type ValidateCodeResult, type ValueSet, type ValueSetCompose, type ValueSetExpansion, type ValueSetMemberDecided, type ValueSetMemberUndetermined, type ValueSetMembership, applyComplexMap, applyGem, approximateMatch, asTermType, brandsFor, buildSubsumption, codeableConcept, coding, consistsOf, defaultStatusMapper, doseFormsOf, expand, genericFor, getArray, getBoolean, getConcept, getNumber, getString, ingredientsOf, invertGem, isA, isJsonObject, isSynonymTermType, isUnknownSystem, loadCodeSystem, loadComplexMap, loadConceptMap, loadGems, loadRxNormGraph, loadUcumEssence, loadValueSet, lookup, makeStatus, matchesFilter, parseCsv, parseCsvSource, parseFhirCodeSystem, parseFixedWidth, parseRrf, parseRrfLine, parseUcum, reduce, relatedByRela, resolveNdc, resolveSystem, sliceField, translate, ucumEqual, unsupportedOps, validateCode, validateCodeInValueSet, validateUcum };