@instruments/taxonomy 1.1.0 → 1.1.1

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
@@ -201,8 +201,8 @@ type RelationPredicate =
201
201
  | "related-to";
202
202
 
203
203
  declare const TAXONOMY_BASE_URI: "https://taxonomy.materialinstruments.com";
204
- declare const TAXONOMY_SNAPSHOT: "2026-08-30";
205
- declare const TAXONOMY_VERSION: "1.1.0";
204
+ declare const TAXONOMY_SNAPSHOT: "2026-08-31";
205
+ declare const TAXONOMY_VERSION: "1.1.1";
206
206
  type CanonicalConceptUri = `${typeof TAXONOMY_BASE_URI}/id/${string}`;
207
207
  type LifecycleStatus = "active" | "deprecated";
208
208
  interface Lifecycle {
@@ -335,8 +335,8 @@ declare const TAXONOMY_CORPUS_METADATA: {
335
335
  readonly lexicalEntryCount: number;
336
336
  readonly nodeCount: number;
337
337
  readonly revision: string;
338
- readonly snapshot: "2026-08-30";
339
- readonly version: "1.1.0";
338
+ readonly snapshot: "2026-08-31";
339
+ readonly version: "1.1.1";
340
340
  };
341
341
 
342
342
  export { type AxisNode, COLOR_SCOPE_REFERENCE_KINDS, type CanonicalConceptUri, type ColorScopeReferenceKind, type ColorScopeTarget, type ConceptNode, type ExternalReference, type FacetNode, type Governance, type GraphPredicate, KNOWLEDGE_GRAPH, type KnowledgeGraph, type KnowledgeGraphEdge, type KnowledgeGraphNode, LEXICAL_ENTRIES, type LexicalContext, type LexicalEntry, type LexicalTarget, type Lifecycle, type LifecycleStatus, type PeriodSpan, type SearchedWithout, type StyleKind, TAXONOMY_BASE_URI, TAXONOMY_CORPUS_METADATA, TAXONOMY_CORPUS_REVISION, TAXONOMY_SNAPSHOT, TAXONOMY_VERSION, type TaxonomyTarget, type TermProvenance, type TermUsage, type UsageWithheld };
package/dist/index.js CHANGED
@@ -1251,14 +1251,28 @@ var FINISH_TERMS = [
1251
1251
  ...FINISH_TEXTURE_TERMS
1252
1252
  ];
1253
1253
 
1254
+ // src/search-corpus-source.ts
1255
+ var MATERIALGRAPH_SEARCH_CORPUS_COMMIT = "53df40868bfb09bfe69bc66c455c051e34005ae1";
1256
+ var MATERIALGRAPH_SEARCH_CORPUS_PATH = "packages/products/src/benchmark/fixtures/benchmark-cases-2026-07-31.1.json";
1257
+ var MATERIALGRAPH_SEARCH_CORPUS_SNAPSHOT = "2026-07-31";
1258
+ var MATERIALGRAPH_SEARCH_CORPUS = `materialgraph@${MATERIALGRAPH_SEARCH_CORPUS_COMMIT}:${MATERIALGRAPH_SEARCH_CORPUS_PATH}`;
1259
+ var searchCorpusEvidence = (phrases) => `${MATERIALGRAPH_SEARCH_CORPUS} (244-query external search corpus; phrase and admission evidence: ${phrases}; canonical boundary authored by Taxonomy)`;
1260
+
1254
1261
  // src/axes/format.ts
1255
1262
  var SOURCE2 = "DesignShop frozen estate format vocabulary";
1256
1263
  var SNAPSHOT2 = "2026-08-25";
1257
- var term3 = (slug, label, definition) => ({
1264
+ var SEARCH_REVIEW_DATE = "2026-08-31";
1265
+ var searchCorpusProvenance = (evidence) => ({
1266
+ basis: "evidenced",
1267
+ snapshot: MATERIALGRAPH_SEARCH_CORPUS_SNAPSHOT,
1268
+ source: searchCorpusEvidence(evidence)
1269
+ });
1270
+ var term3 = (slug, label, definition, extra = {}) => ({
1258
1271
  definition,
1259
1272
  label,
1260
1273
  provenance: { basis: "evidenced", snapshot: SNAPSHOT2, source: SOURCE2 },
1261
- slug
1274
+ slug,
1275
+ ...extra
1262
1276
  });
1263
1277
  var FORMAT_TERMS = [
1264
1278
  term3("area-rug", "Area rug", "A bounded loose-laid textile floor covering."),
@@ -1282,6 +1296,16 @@ var FORMAT_TERMS = [
1282
1296
  "Mural",
1283
1297
  "Supplied as a multi-panel image composed into one continuous scene."
1284
1298
  ),
1299
+ term3(
1300
+ "mosaic",
1301
+ "Mosaic",
1302
+ "Supplied as small pieces assembled or mounted together to install as one composed field, independent of material and visible motif.",
1303
+ {
1304
+ introducedAt: SEARCH_REVIEW_DATE,
1305
+ provenance: searchCorpusProvenance("mosaic"),
1306
+ reviewedAt: SEARCH_REVIEW_DATE
1307
+ }
1308
+ ),
1285
1309
  term3(
1286
1310
  "panel",
1287
1311
  "Panel",
@@ -1303,6 +1327,28 @@ var FORMAT_TERMS = [
1303
1327
  "A large rigid sheet intended to minimise joints or be fabricated to shape."
1304
1328
  ),
1305
1329
  term3("tile", "Tile", "A discrete modular surface unit."),
1330
+ term3(
1331
+ "penny-round",
1332
+ "Penny round",
1333
+ "A small round tile unit supplied for installation as a field, independent of its material and the layout made from it.",
1334
+ {
1335
+ altLabels: ["penny tile"],
1336
+ broaderSlug: "tile",
1337
+ introducedAt: SEARCH_REVIEW_DATE,
1338
+ provenance: searchCorpusProvenance("penny-tile"),
1339
+ reviewedAt: SEARCH_REVIEW_DATE
1340
+ }
1341
+ ),
1342
+ term3(
1343
+ "veneer",
1344
+ "Veneer",
1345
+ "A thin facing layer supplied to be bonded or fixed to a substrate, independent of the material from which the facing is made.",
1346
+ {
1347
+ introducedAt: SEARCH_REVIEW_DATE,
1348
+ provenance: searchCorpusProvenance("veneer"),
1349
+ reviewedAt: SEARCH_REVIEW_DATE
1350
+ }
1351
+ ),
1306
1352
  term3(
1307
1353
  "wide-plank",
1308
1354
  "Wide plank",
@@ -1341,6 +1387,19 @@ var standardCrossoverTerm = (slug, label, definition, source) => ({
1341
1387
  source
1342
1388
  }
1343
1389
  });
1390
+ var searchCorpusMaterial = (slug, label, definition, broaderSlug, referenceSource) => ({
1391
+ broaderSlug,
1392
+ definition,
1393
+ introducedAt: "2026-08-31",
1394
+ label,
1395
+ provenance: {
1396
+ basis: "evidenced",
1397
+ snapshot: MATERIALGRAPH_SEARCH_CORPUS_SNAPSHOT,
1398
+ source: `${searchCorpusEvidence(label)}; ${referenceSource}`
1399
+ },
1400
+ reviewedAt: "2026-08-31",
1401
+ slug
1402
+ });
1344
1403
  var MATERIAL_TERMS = [
1345
1404
  crossoverTerm(
1346
1405
  "brass",
@@ -1433,6 +1492,13 @@ var MATERIAL_TERMS = [
1433
1492
  "An iron-carbon alloy family spanning many grades rather than one uniform product.",
1434
1493
  CROSSOVER_DEFINITION_SOURCES.steel
1435
1494
  ),
1495
+ searchCorpusMaterial(
1496
+ "stainless-steel",
1497
+ "Stainless steel",
1498
+ "A corrosion-resistant steel alloy family containing sufficient chromium to form a protective passive layer, named as a bulk material rather than a surface finish or colour.",
1499
+ "steel",
1500
+ CROSSOVER_DEFINITION_SOURCES.steel
1501
+ ),
1436
1502
  crossoverTerm(
1437
1503
  "wood",
1438
1504
  "Wood",
@@ -1446,6 +1512,13 @@ var MATERIAL_TERMS = [
1446
1512
  CROSSOVER_DEFINITION_SOURCES.oak,
1447
1513
  "wood"
1448
1514
  ),
1515
+ searchCorpusMaterial(
1516
+ "white-oak",
1517
+ "White oak",
1518
+ "Timber from the white-oak species group within the genus Quercus, named as a wood material rather than a colour or surface finish.",
1519
+ "oak",
1520
+ CROSSOVER_DEFINITION_SOURCES.oak
1521
+ ),
1449
1522
  crossoverTerm(
1450
1523
  "teak",
1451
1524
  "Teak",
@@ -2673,8 +2746,8 @@ var uniclass2 = (slug, label, match) => ({
2673
2746
  match,
2674
2747
  scheme: "uniclass"
2675
2748
  });
2676
- var searchedUniclass = (query) => ({
2677
- date: "2026-08-27",
2749
+ var searchedUniclass = (query, date = "2026-08-27") => ({
2750
+ date,
2678
2751
  query,
2679
2752
  scheme: "uniclass",
2680
2753
  via: "uniclass.thenbs.com/taxon, Pr table walked from Pr_20 to Pr_90"
@@ -2683,6 +2756,7 @@ var ESTATE2 = "DesignShop frozen estate and Material Instruments product vocabul
2683
2756
  var ESTATE_SNAPSHOT2 = "2026-08-25";
2684
2757
  var CORPUS2 = "Material Bank catalogue, us_hierarchy_category_v2 level-2 rollup";
2685
2758
  var CORPUS_SNAPSHOT2 = "2026-08-27";
2759
+ var SEARCH_REVIEW_DATE2 = "2026-08-31";
2686
2760
  var term6 = (slug, label, definition, extra = {}) => ({
2687
2761
  definition,
2688
2762
  label,
@@ -2697,6 +2771,19 @@ var fromCorpus = (slug, label, definition, extra = {}) => ({
2697
2771
  slug,
2698
2772
  ...extra
2699
2773
  });
2774
+ var fromSearchCorpus = (slug, label, definition, extra = {}) => ({
2775
+ definition,
2776
+ introducedAt: SEARCH_REVIEW_DATE2,
2777
+ label,
2778
+ provenance: {
2779
+ basis: "evidenced",
2780
+ snapshot: MATERIALGRAPH_SEARCH_CORPUS_SNAPSHOT,
2781
+ source: searchCorpusEvidence(label)
2782
+ },
2783
+ reviewedAt: SEARCH_REVIEW_DATE2,
2784
+ slug,
2785
+ ...extra
2786
+ });
2700
2787
  var PRODUCT_CATEGORY_TERMS = [
2701
2788
  term6(
2702
2789
  "tile",
@@ -2711,13 +2798,16 @@ var PRODUCT_CATEGORY_TERMS = [
2711
2798
  "Carpet and rug",
2712
2799
  "A textile floor covering, fixed or loose laid.",
2713
2800
  {
2801
+ altLabels: ["carpet", "rug"],
2714
2802
  external: [
2715
2803
  uniclass2(
2716
2804
  "Pr_35_57_11",
2717
2805
  "Carpets, carpet tiles, coverings, underlays and mats",
2718
2806
  "exact"
2719
2807
  )
2720
- ]
2808
+ ],
2809
+ introducedAt: "2026-08-30",
2810
+ reviewedAt: "2026-08-31"
2721
2811
  }
2722
2812
  ),
2723
2813
  term6(
@@ -2886,6 +2976,113 @@ var PRODUCT_CATEGORY_TERMS = [
2886
2976
  "Ceiling system",
2887
2977
  "A suspended or applied ceiling product supplied with its own grid, carrier or fixing method.",
2888
2978
  { external: [uniclass2("Pr_35_93_13", "Ceiling infill units", "close")] }
2979
+ ),
2980
+ fromSearchCorpus(
2981
+ "sconce",
2982
+ "Sconce",
2983
+ "A wall-mounted luminaire supplied as a complete light fitting, not the wall it mounts to or the light effect it produces.",
2984
+ {
2985
+ altLabels: ["wall sconce", "wall light"],
2986
+ broaderSlug: "luminaire",
2987
+ searchedWithout: [
2988
+ searchedUniclass("sconce, wall sconce, wall light", SEARCH_REVIEW_DATE2)
2989
+ ]
2990
+ }
2991
+ ),
2992
+ fromSearchCorpus(
2993
+ "chandelier",
2994
+ "Chandelier",
2995
+ "A suspended decorative luminaire with multiple arms, branches or light sources, independent of the ceiling system supporting it.",
2996
+ {
2997
+ broaderSlug: "luminaire",
2998
+ external: [uniclass2("Pr_70_70_48_13", "Chandeliers", "exact")]
2999
+ }
3000
+ ),
3001
+ fromSearchCorpus(
3002
+ "pendant-luminaire",
3003
+ "Pendant luminaire",
3004
+ "A luminaire suspended from above as an individual fitting, distinct from its cable, track or ceiling support.",
3005
+ {
3006
+ altLabels: ["pendant", "pendant light"],
3007
+ broaderSlug: "luminaire",
3008
+ external: [uniclass2("Pr_70_70_48_62", "Pendant luminaires", "exact")]
3009
+ }
3010
+ ),
3011
+ fromSearchCorpus(
3012
+ "track-luminaire",
3013
+ "Track luminaire",
3014
+ "A luminaire made to attach to and draw power from a lighting track, distinct from the track and its electrical accessories.",
3015
+ {
3016
+ altLabels: ["track lighting", "track light"],
3017
+ broaderSlug: "luminaire",
3018
+ searchedWithout: [
3019
+ searchedUniclass("track luminaire, track light", SEARCH_REVIEW_DATE2)
3020
+ ]
3021
+ }
3022
+ ),
3023
+ fromSearchCorpus(
3024
+ "sofa",
3025
+ "Sofa",
3026
+ "An upholstered seating product for two or more people, independent of its upholstery material or room placement.",
3027
+ {
3028
+ altLabels: ["couch"],
3029
+ broaderSlug: "seating",
3030
+ external: [uniclass2("Pr_40_50_12_81", "Sofas", "exact")]
3031
+ }
3032
+ ),
3033
+ fromSearchCorpus(
3034
+ "mosaic-tile",
3035
+ "Mosaic tile",
3036
+ "A tile product composed of small tesserae supplied loose or mounted for installation as a field, independent of their material or visible motif.",
3037
+ {
3038
+ altLabels: ["mosaic"],
3039
+ broaderSlug: "tile",
3040
+ external: [uniclass2("Pr_35_93_96_53", "Mosaic tiles", "exact")]
3041
+ }
3042
+ ),
3043
+ fromSearchCorpus(
3044
+ "wall-panel",
3045
+ "Wall panel",
3046
+ "A panel product supplied to form or cover the visible face of a wall, independent of the panel material and the wall element behind it.",
3047
+ {
3048
+ altLabels: ["wall panelling", "wall paneling"],
3049
+ broaderSlug: "wallcovering",
3050
+ searchedWithout: [
3051
+ searchedUniclass(
3052
+ "wall panel, wall panelling, wall paneling",
3053
+ SEARCH_REVIEW_DATE2
3054
+ )
3055
+ ]
3056
+ }
3057
+ ),
3058
+ fromSearchCorpus(
3059
+ "acoustic-ceiling-system",
3060
+ "Acoustic ceiling system",
3061
+ "A ceiling system specified to absorb or control sound, independent of the material, module format or space in which it is installed.",
3062
+ {
3063
+ altLabels: ["acoustic ceiling"],
3064
+ broaderSlug: "ceiling-system",
3065
+ searchedWithout: [
3066
+ searchedUniclass(
3067
+ "acoustic ceiling system, acoustic ceiling",
3068
+ SEARCH_REVIEW_DATE2
3069
+ )
3070
+ ]
3071
+ }
3072
+ ),
3073
+ fromSearchCorpus(
3074
+ "upholstery-textile",
3075
+ "Upholstery textile",
3076
+ "A textile product supplied for covering furniture, distinct from the furniture, the upholstery application and the fibre or hide material.",
3077
+ {
3078
+ broaderSlug: "textile",
3079
+ searchedWithout: [
3080
+ searchedUniclass(
3081
+ "upholstery textile, upholstery fabric",
3082
+ SEARCH_REVIEW_DATE2
3083
+ )
3084
+ ]
3085
+ }
2889
3086
  )
2890
3087
  ];
2891
3088
 
@@ -6916,8 +7113,9 @@ var resolveReference = (reference) => INDEX.byKey.get(canonicalKey(reference));
6916
7113
 
6917
7114
  // src/v1.ts
6918
7115
  var TAXONOMY_BASE_URI = "https://taxonomy.materialinstruments.com";
6919
- var TAXONOMY_SNAPSHOT = "2026-08-30";
6920
- var TAXONOMY_VERSION = "1.1.0";
7116
+ var TAXONOMY_SNAPSHOT = "2026-08-31";
7117
+ var TAXONOMY_VERSION = "1.1.1";
7118
+ var PUBLISHED_V1_BASELINE = "2026-08-30";
6921
7119
  var compareText = (left, right) => {
6922
7120
  if (left < right) {
6923
7121
  return -1;
@@ -6952,8 +7150,8 @@ var lifecycleFor = (term8) => {
6952
7150
  successorAxis.facets.length > 1 || successorAxis.facets[0]?.slug !== successorAxis.slug
6953
7151
  );
6954
7152
  return {
6955
- introducedAt: TAXONOMY_SNAPSHOT,
6956
- reviewedAt: TAXONOMY_SNAPSHOT,
7153
+ introducedAt: term8?.introducedAt ?? PUBLISHED_V1_BASELINE,
7154
+ reviewedAt: term8?.reviewedAt ?? term8?.introducedAt ?? PUBLISHED_V1_BASELINE,
6957
7155
  status: term8?.status ?? "active",
6958
7156
  ...supersededBy === void 0 ? {} : { supersededBy }
6959
7157
  };
@@ -7172,9 +7370,9 @@ var COLOR_SCOPE_REFERENCE_KINDS = [
7172
7370
  "palette-mood",
7173
7371
  "temperature-level"
7174
7372
  ];
7175
- var lexicalGovernance = (explanation, provenance) => ({
7373
+ var lexicalGovernance = (explanation, provenance, lifecycle = lifecycleFor()) => ({
7176
7374
  explanation,
7177
- lifecycle: lifecycleFor(),
7375
+ lifecycle,
7178
7376
  provenance,
7179
7377
  steward: "@instruments/taxonomy"
7180
7378
  });
@@ -7199,7 +7397,7 @@ var crossoverAmbiguity = (phrase, taxonomyUri, colorScopeIdentifier, explanation
7199
7397
  "Taxonomy preserves the evidenced readings without assigning a default, role, contextual preference, or consumer route.",
7200
7398
  {
7201
7399
  basis: "evidenced",
7202
- snapshot: TAXONOMY_SNAPSHOT,
7400
+ snapshot: PUBLISHED_V1_BASELINE,
7203
7401
  source
7204
7402
  }
7205
7403
  ),
@@ -7220,7 +7418,7 @@ var crossoverEquivalent = (phrase, taxonomyUri, explanation, source) => ({
7220
7418
  "Taxonomy records the evidenced material reading without assigning a consumer route.",
7221
7419
  {
7222
7420
  basis: "evidenced",
7223
- snapshot: TAXONOMY_SNAPSHOT,
7421
+ snapshot: PUBLISHED_V1_BASELINE,
7224
7422
  source
7225
7423
  }
7226
7424
  ),
@@ -7228,7 +7426,7 @@ var crossoverEquivalent = (phrase, taxonomyUri, explanation, source) => ({
7228
7426
  phrase,
7229
7427
  target: { authority: "taxonomy", uri: taxonomyUri }
7230
7428
  });
7231
- var crossoverTaxonomyAmbiguity = (phrase, readings, explanation, source) => {
7429
+ var crossoverTaxonomyAmbiguity = (phrase, readings, explanation, source, snapshot = PUBLISHED_V1_BASELINE, lifecycle = lifecycleFor()) => {
7232
7430
  const [first, second] = readings;
7233
7431
  return {
7234
7432
  explanation,
@@ -7236,9 +7434,10 @@ var crossoverTaxonomyAmbiguity = (phrase, readings, explanation, source) => {
7236
7434
  "Taxonomy preserves the evidenced readings without assigning a default, role, contextual preference, or consumer route.",
7237
7435
  {
7238
7436
  basis: "evidenced",
7239
- snapshot: TAXONOMY_SNAPSHOT,
7437
+ snapshot,
7240
7438
  source
7241
- }
7439
+ },
7440
+ lifecycle
7242
7441
  ),
7243
7442
  outcome: "ambiguous",
7244
7443
  phrase,
@@ -7249,13 +7448,28 @@ var crossoverTaxonomyAmbiguity = (phrase, readings, explanation, source) => {
7249
7448
  };
7250
7449
  };
7251
7450
  var AUTHORED_LEXICAL_ENTRIES = [
7451
+ crossoverTaxonomyAmbiguity(
7452
+ "mosaic",
7453
+ [
7454
+ `${TAXONOMY_BASE_URI}/id/product-category/mosaic-tile`,
7455
+ `${TAXONOMY_BASE_URI}/id/format/mosaic`
7456
+ ],
7457
+ "Mosaic can name a purchasable mosaic-tile product or the small-piece supply format; it is neither inherently a pattern nor a substance. Consumers must union any exact ColorScope named-paint reading with these domain readings rather than let an exact Taxonomy phrase shadow the external identity.",
7458
+ `${searchCorpusEvidence("mosaic")}; Uniclass Pr_35_93_96_53 Mosaic tiles; consumer authority-union boundary reviewed 2026-08-31`,
7459
+ MATERIALGRAPH_SEARCH_CORPUS_SNAPSHOT,
7460
+ {
7461
+ introducedAt: TAXONOMY_SNAPSHOT,
7462
+ reviewedAt: TAXONOMY_SNAPSHOT,
7463
+ status: "active"
7464
+ }
7465
+ ),
7252
7466
  {
7253
7467
  explanation: "Blue is a ColorScope colour-family reading; Taxonomy references that authority rather than minting a rival colour identity.",
7254
7468
  governance: lexicalGovernance(
7255
7469
  "The ColorScope family is the single governed reading of the unqualified colour word.",
7256
7470
  {
7257
7471
  basis: "vendored",
7258
- snapshot: TAXONOMY_SNAPSHOT,
7472
+ snapshot: PUBLISHED_V1_BASELINE,
7259
7473
  source: "@instruments/colorscope COLOR_FAMILIES"
7260
7474
  }
7261
7475
  ),
@@ -7553,7 +7767,7 @@ var AUTHORED_LEXICAL_ENTRIES = [
7553
7767
  "The two readings are deliberately separate and context may select only the preference declared here.",
7554
7768
  {
7555
7769
  basis: "evidenced",
7556
- snapshot: TAXONOMY_SNAPSHOT,
7770
+ snapshot: PUBLISHED_V1_BASELINE,
7557
7771
  source: crossoverSource("walnut")
7558
7772
  }
7559
7773
  ),
@@ -7595,6 +7809,17 @@ var lexicalPhrases = (term8) => [term8.slug, term8.label, ...term8.altLabels ??
7595
7809
  (phrase, index, phrases) => phrase.length > 0 && phrases.indexOf(phrase) === index
7596
7810
  );
7597
7811
  var targetKey = (target) => target.authority === "taxonomy" ? `taxonomy:${target.uri}` : `colorscope:${target.referenceKind}:${target.identifier}`;
7812
+ var inferredLifecycle = (readings) => {
7813
+ const terms = readings.flatMap((reading) => reading.terms);
7814
+ const [introducedAt] = terms.map((term8) => term8.introducedAt ?? PUBLISHED_V1_BASELINE).toSorted(compareText);
7815
+ const reviewedAt = terms.map(
7816
+ (term8) => term8.reviewedAt ?? term8.introducedAt ?? PUBLISHED_V1_BASELINE
7817
+ ).toSorted(compareText).at(-1);
7818
+ if (introducedAt === void 0 || reviewedAt === void 0) {
7819
+ throw new Error("Inferred lexical reading has no source term lifecycle.");
7820
+ }
7821
+ return { introducedAt, reviewedAt, status: "active" };
7822
+ };
7598
7823
  var inferredLexicalEntries = () => {
7599
7824
  const authored = new Set(
7600
7825
  AUTHORED_LEXICAL_ENTRIES.map((entry) => entry.phrase)
@@ -7603,18 +7828,24 @@ var inferredLexicalEntries = () => {
7603
7828
  for (const location of AUTHORING_LOCATIONS) {
7604
7829
  const target = targetForLocation(location);
7605
7830
  for (const phrase of lexicalPhrases(location.term)) {
7606
- const targets = targetsByPhrase.get(phrase) ?? [];
7607
- if (!targets.some((candidate) => targetKey(candidate) === targetKey(target))) {
7608
- targets.push(target);
7831
+ const readings = targetsByPhrase.get(phrase) ?? [];
7832
+ const existing = readings.find(
7833
+ (candidate) => targetKey(candidate.target) === targetKey(target)
7834
+ );
7835
+ if (existing === void 0) {
7836
+ readings.push({ target, terms: [location.term] });
7837
+ } else {
7838
+ existing.terms.push(location.term);
7609
7839
  }
7610
- targetsByPhrase.set(phrase, targets);
7840
+ targetsByPhrase.set(phrase, readings);
7611
7841
  }
7612
7842
  }
7613
- return [...targetsByPhrase].filter(([phrase]) => !authored.has(phrase)).map(([phrase, targets]) => {
7614
- const [first, second, ...rest] = targets;
7843
+ return [...targetsByPhrase].filter(([phrase]) => !authored.has(phrase)).map(([phrase, readings]) => {
7844
+ const [first, second, ...rest] = readings;
7615
7845
  if (first === void 0) {
7616
7846
  throw new Error(`Lexical phrase "${phrase}" has no reading.`);
7617
7847
  }
7848
+ const lifecycle = inferredLifecycle(readings);
7618
7849
  if (second === void 0) {
7619
7850
  return {
7620
7851
  explanation: `The published spelling \u201C${phrase}\u201D has one governed reading.`,
@@ -7622,13 +7853,14 @@ var inferredLexicalEntries = () => {
7622
7853
  "The reading is derived from a canonical label, slug, alternate label, or observed source spelling.",
7623
7854
  {
7624
7855
  basis: "evidenced",
7625
- snapshot: TAXONOMY_SNAPSHOT,
7856
+ snapshot: lifecycle.reviewedAt,
7626
7857
  source: "Taxonomy V1 authored term dictionaries"
7627
- }
7858
+ },
7859
+ lifecycle
7628
7860
  ),
7629
7861
  outcome: "equivalent",
7630
7862
  phrase,
7631
- target: first
7863
+ target: first.target
7632
7864
  };
7633
7865
  }
7634
7866
  return {
@@ -7637,13 +7869,18 @@ var inferredLexicalEntries = () => {
7637
7869
  "No context-independent primary reading has been governed.",
7638
7870
  {
7639
7871
  basis: "evidenced",
7640
- snapshot: TAXONOMY_SNAPSHOT,
7872
+ snapshot: lifecycle.reviewedAt,
7641
7873
  source: "Colliding Taxonomy V1 authored term spellings"
7642
- }
7874
+ },
7875
+ lifecycle
7643
7876
  ),
7644
7877
  outcome: "ambiguous",
7645
7878
  phrase,
7646
- readings: [first, second, ...rest]
7879
+ readings: [
7880
+ first.target,
7881
+ second.target,
7882
+ ...rest.map(({ target }) => target)
7883
+ ]
7647
7884
  };
7648
7885
  });
7649
7886
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instruments/taxonomy",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Canonical data-only interiors and architecture knowledge graph and lexical corpus.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {
@@ -23,14 +23,6 @@
23
23
  "publishConfig": {
24
24
  "access": "public"
25
25
  },
26
- "scripts": {
27
- "build": "rm -rf dist && tsup",
28
- "lint": "howells-check .",
29
- "prepare": "[ -d dist ] || pnpm build",
30
- "sync:colorscope": "vitest run src/colorscope-sync.test.ts",
31
- "test": "vitest run",
32
- "typecheck": "tsc --noEmit"
33
- },
34
26
  "devDependencies": {
35
27
  "@howells/lint": "^1.0.0",
36
28
  "@instruments/colorscope": "7.3.0",
@@ -38,5 +30,13 @@
38
30
  "tsup": "^8.5.1",
39
31
  "typescript": "^5.7.0",
40
32
  "vitest": "^4.0.0"
33
+ },
34
+ "scripts": {
35
+ "build": "rm -rf dist && tsup",
36
+ "lint": "howells-check .",
37
+ "smoke:packed": "node --experimental-strip-types scripts/smoke-packed-core.ts",
38
+ "sync:colorscope": "vitest run src/colorscope-sync.test.ts",
39
+ "test": "vitest run",
40
+ "typecheck": "tsc --noEmit"
41
41
  }
42
- }
42
+ }