glossarist 0.4.20 → 0.4.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glossarist",
3
- "version": "0.4.20",
3
+ "version": "0.4.22",
4
4
  "description": "JavaScript SDK for Glossarist GCR packages — read, write, validate, and manage terminology concepts",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -4,25 +4,24 @@
4
4
  // PartitiveRelation hash. Idempotent. Used by the parser when loading
5
5
  // legacy YAML; available as a public API for one-shot dataset migrations.
6
6
  //
7
- // Field mapping (per TODO.partitive-relation-v2 items 01–05):
7
+ // Field mapping (per TODO.partitive-relation-v2 items 01–05 and the
8
+ // ISO 704:2022 correction):
8
9
  //
9
10
  // comprehensive → comprehensive (unchanged shape)
10
- // parts: [ref, ...] → partitives: [{ ref, certainty: 'confirmed' }, ...]
11
+ // parts: [ref, ...] → partitives: [{ ref, multiplicity: 'compulsory' }, ...]
11
12
  // enumeration: open → completeness: partial
12
13
  // enumeration: closed→ completeness: complete
13
- // markers: [double] ┐
14
- // markers: [dashed] ├→ plurality: { is_shared, is_uncertain }
15
- // markers: [double, dashed] ┘
16
- // content: "..." → (dropped — structural edges carry no prose)
14
+ // markers: [...] → (dropped — v2 uses per-member multiplicity
15
+ // + is_delimiting; v1 markers encoded the
16
+ // same information imprecisely and cannot
17
+ // round-trip losslessly)
18
+ // content: "..." → (dropped — structural edges carry no prose)
17
19
  //
18
20
  // Cardinality check: v1 allowed [1..*] parts; v2 requires [2..*].
19
21
  // A v1 hyperedge with exactly 1 part cannot migrate to v2 and is
20
22
  // returned with a `migrationWarning` field set so callers can decide
21
23
  // whether to surface it (the parser drops these with a warning).
22
24
 
23
- const MARKER_DOUBLE = 'double';
24
- const MARKER_DASHED = 'dashed';
25
-
26
25
  export function migrateHyperedgeToRelation(v1Hash) {
27
26
  if (v1Hash == null) return null;
28
27
  if (Array.isArray(v1Hash)) {
@@ -36,17 +35,12 @@ export function migrateHyperedgeToRelation(v1Hash) {
36
35
  const parts = Array.isArray(v1Hash.parts) ? v1Hash.parts : [];
37
36
  out.partitives = parts.map(ref => ({
38
37
  ref: { ...ref },
39
- certainty: 'confirmed',
38
+ multiplicity: 'compulsory',
40
39
  }));
41
40
 
42
41
  out.completeness = _migrateEnumeration(v1Hash.enumeration);
43
42
 
44
- const plurality = _migrateMarkers(v1Hash.markers);
45
- if (plurality != null) out.plurality = plurality;
46
-
47
- // v1 content field is dropped per TODO.partitive-relation-v2 item 04.
48
- // Caller (parser) may surface this as a warning if the text matters.
49
-
43
+ // v1 content + markers fields are dropped per TODO.partitive-relation-v2.
50
44
  if (parts.length < 2) {
51
45
  out.migrationWarning =
52
46
  `v1 PartitiveHyperedge had ${parts.length} part(s); v2 requires ≥2. ` +
@@ -59,12 +53,19 @@ export function migrateHyperedgeToRelation(v1Hash) {
59
53
  `move valuable text to the comprehensive concept's notes).`;
60
54
  }
61
55
 
56
+ if (Array.isArray(v1Hash.markers) && v1Hash.markers.length > 0) {
57
+ out.migrationWarning = (out.migrationWarning ?? '') +
58
+ ` v1 'markers' field (${v1Hash.markers.join(', ')}) was dropped; ` +
59
+ `v2 uses per-member 'multiplicity' + 'is_delimiting'. Reviewer ` +
60
+ `should set these per partitive based on ISO 704:2022 notation.`;
61
+ }
62
+
62
63
  return out;
63
64
  }
64
65
 
65
66
  // Inverse — v2 → v1 — exists only for tooling that must round-trip
66
67
  // through v1 consumers. NOT used by the parser; the serializer emits
67
- // v2 only.
68
+ // v2 only. Lossy: drops criterion, multiplicity, is_delimiting.
68
69
  export function downgradeRelationToHyperedge(v2Hash) {
69
70
  if (v2Hash == null) return null;
70
71
  if (Array.isArray(v2Hash)) {
@@ -78,11 +79,8 @@ export function downgradeRelationToHyperedge(v2Hash) {
78
79
  out.parts = (v2Hash.partitives ?? []).map(m => ({ ...(m.ref ?? {}) }));
79
80
  out.enumeration = _downgradeCompleteness(v2Hash.completeness);
80
81
 
81
- const markers = _downgradePlurality(v2Hash.plurality);
82
- if (markers.length > 0) out.markers = markers;
83
-
84
- // criterion has no v1 equivalent — dropped silently
85
- // per-member certainty has no v1 equivalent — dropped silently
82
+ // criterion, multiplicity, is_delimiting have no v1 equivalent —
83
+ // dropped silently.
86
84
 
87
85
  return out;
88
86
  }
@@ -99,27 +97,3 @@ function _downgradeCompleteness(value) {
99
97
  if (value === 'partial') return 'open';
100
98
  return 'closed';
101
99
  }
102
-
103
- function _migrateMarkers(markers) {
104
- if (!Array.isArray(markers) || markers.length === 0) return null;
105
-
106
- const isShared = markers.includes(MARKER_DOUBLE);
107
- const isUncertain = markers.includes(MARKER_DASHED);
108
-
109
- // Per TODO.partitive-relation-v2 item 03 migration table:
110
- // [dashed] alone is semantically odd (broken line qualifies
111
- // plurality; without double, what's being qualified?). We
112
- // migrate it to is_shared=false, is_uncertain=true and rely on
113
- // the PartitiveRelationCoherenceRule to warn.
114
- if (!isShared && !isUncertain) return null;
115
-
116
- return { is_shared: isShared, is_uncertain: isUncertain };
117
- }
118
-
119
- function _downgradePlurality(plurality) {
120
- if (plurality == null) return [];
121
- const markers = [];
122
- if (plurality.is_shared) markers.push(MARKER_DOUBLE);
123
- if (plurality.is_uncertain) markers.push(MARKER_DASHED);
124
- return markers;
125
- }
@@ -38,7 +38,6 @@ export {
38
38
  // backward-compat input. New code should use v2 exclusively.
39
39
  export { PartitiveRelation } from './partitive-relation.js';
40
40
  export { PartitiveMember } from './partitive-member.js';
41
- export { TypeSharedPlurality } from './type-shared-plurality.js';
42
41
  export {
43
42
  COMPLETENESS,
44
43
  COMPLETENESS_VALUES,
@@ -46,11 +45,11 @@ export {
46
45
  isValidCompleteness,
47
46
  } from './completeness.js';
48
47
  export {
49
- MEMBER_CERTAINTY,
50
- MEMBER_CERTAINTY_VALUES,
51
- DEFAULT_MEMBER_CERTAINTY,
52
- isValidMemberCertainty,
53
- } from './member-certainty.js';
48
+ MULTIPLICITY,
49
+ MULTIPLICITY_VALUES,
50
+ DEFAULT_MULTIPLICITY,
51
+ isValidMultiplicity,
52
+ } from './multiplicity.js';
54
53
 
55
54
  // v1 → v2 migration helper. Pure function; idempotent.
56
55
  export {
@@ -0,0 +1,24 @@
1
+ // Multiplicity — ISO 704:2022 partitive member multiplicity.
2
+ //
3
+ // Encodes the diagram line notation as structured data:
4
+ // compulsory — 1 solid line (must exist in every instance)
5
+ // optional — 1 dashed line (exists in some instances only)
6
+ // compulsory_multiple — 2 solid lines (multiple must exist)
7
+ // optional_multiple — 2 dashed lines (multiple may exist)
8
+ // at_least_one — 1 solid + 1 dashed line (at least one must exist)
9
+ //
10
+ // Defaults to `compulsory` when omitted.
11
+
12
+ import { makeEnum } from './enum.js';
13
+
14
+ export const MULTIPLICITY = makeEnum('MULTIPLICITY', {
15
+ COMPULSORY: 'compulsory',
16
+ OPTIONAL: 'optional',
17
+ COMPULSORY_MULTIPLE: 'compulsory_multiple',
18
+ OPTIONAL_MULTIPLE: 'optional_multiple',
19
+ AT_LEAST_ONE: 'at_least_one',
20
+ });
21
+
22
+ export const MULTIPLICITY_VALUES = MULTIPLICITY.VALUES;
23
+ export const DEFAULT_MULTIPLICITY = MULTIPLICITY.COMPULSORY;
24
+ export const isValidMultiplicity = MULTIPLICITY.isValid;
@@ -1,21 +1,29 @@
1
1
  // PartitiveMember — one member of a PartitiveRelation.
2
2
  //
3
- // A partitive member carries a ConceptRef (the subordinate concept
4
- // partitive) and optional certainty metadata. A PartitiveMember with
5
- // no certainty field is implicitly confirmed.
3
+ // Carries a ConceptRef (the subordinate concept partitive) plus
4
+ // ISO 704:2022 multiplicity and delimiting metadata.
6
5
  //
7
- // Glossarist extension beyond ISO 704: ISO notation expresses
8
- // plurality-level uncertainty (broken line); per-member certainty
9
- // lets a relation assert "member b is confirmed, member d is possible"
10
- // at the member level.
6
+ // ISO 704:2022 partitive member notation:
7
+ //
8
+ // multiplicity (diagram line notation):
9
+ // compulsory — 1 solid line (must exist in every instance)
10
+ // optional — 1 dashed line (exists in some instances only)
11
+ // compulsory_multiple — 2 solid lines (multiple must exist)
12
+ // optional_multiple — 2 dashed lines (multiple may exist)
13
+ // at_least_one — 1 solid + 1 dashed line (≥1 must exist)
14
+ //
15
+ // is_delimiting (orthogonal, bold 3x-width line in diagram):
16
+ // A delimiting part behaves like a delimiting characteristic:
17
+ // it distinguishes the comprehensive from coordinate concepts.
11
18
 
12
19
  import { GlossaristModel } from './base.js';
13
20
  import { ConceptRef } from './concept-ref.js';
14
21
  import {
15
- MEMBER_CERTAINTY,
16
- DEFAULT_MEMBER_CERTAINTY,
17
- isValidMemberCertainty,
18
- } from './member-certainty.js';
22
+ MULTIPLICITY,
23
+ DEFAULT_MULTIPLICITY,
24
+ MULTIPLICITY_VALUES,
25
+ isValidMultiplicity,
26
+ } from './multiplicity.js';
19
27
 
20
28
  export class PartitiveMember extends GlossaristModel {
21
29
  constructor(data = {}) {
@@ -23,17 +31,22 @@ export class PartitiveMember extends GlossaristModel {
23
31
  this.ref = data.ref instanceof ConceptRef
24
32
  ? data.ref
25
33
  : new ConceptRef(data.ref ?? {});
26
- this.certainty = _resolveCertainty(data.certainty);
34
+ this.multiplicity = _resolveMultiplicity(data.multiplicity);
35
+ this.is_delimiting = data.is_delimiting === true;
27
36
 
28
37
  _assertNonEmptyRef(this.ref);
29
38
  }
30
39
 
31
- get isConfirmed() {
32
- return this.certainty === MEMBER_CERTAINTY.CONFIRMED;
40
+ get isCompulsory() {
41
+ return this.multiplicity === MULTIPLICITY.COMPULSORY;
33
42
  }
34
43
 
35
- get isPossible() {
36
- return this.certainty === MEMBER_CERTAINTY.POSSIBLE;
44
+ get isOptional() {
45
+ return this.multiplicity === MULTIPLICITY.OPTIONAL;
46
+ }
47
+
48
+ get isDelimiting() {
49
+ return this.is_delimiting === true;
37
50
  }
38
51
 
39
52
  identity() {
@@ -42,8 +55,11 @@ export class PartitiveMember extends GlossaristModel {
42
55
 
43
56
  toJSON() {
44
57
  const obj = { ref: this.ref.toJSON() };
45
- if (this.certainty !== DEFAULT_MEMBER_CERTAINTY) {
46
- obj.certainty = this.certainty;
58
+ if (this.multiplicity !== DEFAULT_MULTIPLICITY) {
59
+ obj.multiplicity = this.multiplicity;
60
+ }
61
+ if (this.is_delimiting === true) {
62
+ obj.is_delimiting = true;
47
63
  }
48
64
  return obj;
49
65
  }
@@ -51,7 +67,7 @@ export class PartitiveMember extends GlossaristModel {
51
67
  static identityOf(value) {
52
68
  const v = value ?? {};
53
69
  const ref = v.ref ?? {};
54
- return `${ref.source ?? ''}|${ref.id ?? ''}|${v.certainty ?? DEFAULT_MEMBER_CERTAINTY}`;
70
+ return `${ref.source ?? ''}:${ref.id ?? ''}`;
55
71
  }
56
72
 
57
73
  static fromJSON(data) {
@@ -59,21 +75,22 @@ export class PartitiveMember extends GlossaristModel {
59
75
  }
60
76
  }
61
77
 
62
- function _resolveCertainty(value) {
63
- const cert = value ?? DEFAULT_MEMBER_CERTAINTY;
64
- if (!isValidMemberCertainty(cert)) {
78
+ function _resolveMultiplicity(value) {
79
+ if (value == null) return DEFAULT_MULTIPLICITY;
80
+ if (!isValidMultiplicity(value)) {
65
81
  throw new Error(
66
- `PartitiveMember.certainty has invalid value ${JSON.stringify(value)}; ` +
67
- `must be one of: ${MEMBER_CERTAINTY.VALUES.join(', ')}`,
82
+ `invalid multiplicity ${JSON.stringify(value)}; ` +
83
+ `must be one of ${MULTIPLICITY_VALUES.join(', ')}`,
68
84
  );
69
85
  }
70
- return cert;
86
+ return value;
71
87
  }
72
88
 
73
89
  function _assertNonEmptyRef(ref) {
74
90
  if (!ref.source && !ref.id && !ref.text) {
75
91
  throw new Error(
76
- 'PartitiveMember.ref must be non-empty (source, id, or text required)',
92
+ 'PartitiveMember#ref must be a non-empty ConceptRef ' +
93
+ '(source, id, or text required)',
77
94
  );
78
95
  }
79
96
  }
@@ -1,31 +1,29 @@
1
- // PartitiveRelation — a one-to-many partitive decomposition.
2
- //
3
- // Connects a comprehensive concept (superordinate concept partitive)
4
- // to two or more partitive concepts (subordinate concepts partitive)
5
- // which fitted together constitute the comprehensive.
6
- //
7
- // Renamed from the v1 `PartitiveHyperedge` per TODO.partitive-relation-v2
8
- // item 01. ISO 704 / 1087-1 / 12620 call this a *partitive relation*,
9
- // not a hyperedge.
1
+ // PartitiveRelation — an ISO 704 / ISO 1087-1 / ISO 12620
2
+ // partitive relation connecting a comprehensive concept
3
+ // (superordinate concept partitive) to two or more partitive
4
+ // concepts (subordinate concepts partitive) which fitted together
5
+ // constitute the comprehensive.
10
6
  //
11
7
  // Field renames (v1 → v2):
12
8
  // parts [1..*] → partitives [2..*] (as PartitiveMember)
13
9
  // enumeration: closed|open → completeness: complete|partial
14
- // markers: [double, dashed] → plurality: TypeSharedPlurality (structured)
15
10
  // content: LocalizedString → (dropped — structural edges carry no prose)
16
11
  //
12
+ // Per-member metadata (ISO 704:2022):
13
+ // multiplicity (5 values) + is_delimiting (boolean)
14
+ //
17
15
  // New field:
18
16
  // criterion: LocalizedString [0..1] (ISO 12620 coordinate-concept coherence)
19
17
  //
20
18
  // Distinguished from binary `has_part` / `is_part_of` edges, which
21
- // express pairwise part-of assertions without completeness, plurality,
22
- // or criterion claims. A single partitive should be expressed as a
23
- // binary edge, not a PartitiveRelation (ISO requires "two or more").
19
+ // express pairwise part-of assertions without completeness,
20
+ // multiplicity, or criterion claims. A single partitive should be
21
+ // expressed as a binary edge, not a PartitiveRelation (ISO requires
22
+ // "two or more").
24
23
 
25
24
  import { GlossaristModel } from './base.js';
26
25
  import { ConceptRef } from './concept-ref.js';
27
26
  import { PartitiveMember } from './partitive-member.js';
28
- import { TypeSharedPlurality } from './type-shared-plurality.js';
29
27
  import {
30
28
  COMPLETENESS,
31
29
  COMPLETENESS_VALUES,
@@ -39,11 +37,6 @@ export class PartitiveRelation extends GlossaristModel {
39
37
  this.comprehensive = _ensureComprehensive(data.comprehensive);
40
38
  this.partitives = _ensurePartitives(data.partitives);
41
39
  this.completeness = _resolveCompleteness(data.completeness);
42
- this.plurality = data.plurality == null
43
- ? null
44
- : (data.plurality instanceof TypeSharedPlurality
45
- ? data.plurality
46
- : new TypeSharedPlurality(data.plurality));
47
40
  this.criterion = _normalizeCriterion(data.criterion);
48
41
 
49
42
  _assertNoSelfLoop(this.comprehensive, this.partitives);
@@ -57,7 +50,6 @@ export class PartitiveRelation extends GlossaristModel {
57
50
  // coordinate concepts by definition).
58
51
  get isCoordinate() { return this.partitives.length >= 2; }
59
52
 
60
- hasPlurality() { return this.plurality != null; }
61
53
  hasCriterion() { return this.criterion != null; }
62
54
 
63
55
  identity() {
@@ -70,15 +62,14 @@ export class PartitiveRelation extends GlossaristModel {
70
62
  partitives: this.partitives.map(p => p.toJSON()),
71
63
  completeness: this.completeness,
72
64
  };
73
- if (this.plurality != null) obj.plurality = this.plurality.toJSON();
74
65
  if (this.criterion != null) obj.criterion = { ...this.criterion };
75
66
  return obj;
76
67
  }
77
68
 
78
69
  // Stable identity for diffing: same comprehensive + same partitive
79
70
  // set (by ref identity) = same relation. Changes to completeness,
80
- // plurality, or criterion produce "changed" entries rather than
81
- // add+remove. Matches the v1 hyperedgeIdentity semantics.
71
+ // multiplicity, is_delimiting, or criterion produce "changed"
72
+ // entries rather than add+remove.
82
73
  static identityOf(value) {
83
74
  const v = value ?? {};
84
75
  const c = v.comprehensive ?? {};
@@ -7,16 +7,11 @@
7
7
  // gloss:comprehensive <base>/concept/<comprehensive-id> (named node)
8
8
  // gloss:hasPartitive <base>/concept/<partitive-id> (named node, one per member)
9
9
  // gloss:completeness "complete"|"partial" (literal)
10
- // gloss:hasPlurality <plurality bnode> (when plurality present)
11
10
  // gloss:criterion "..."@lang (one per language, when present)
12
11
  //
13
- // Plurality bnode (when present):
14
- //
15
- // _:b<n>
16
- // rdf:type gloss:TypeSharedPlurality
17
- // gloss:isShared true|false (literal)
18
- // gloss:isUncertain true|false (literal, when non-default)
19
- // gloss:sharedType <base>/concept/<shared-type-id> (when shared_type present)
12
+ // Per-member multiplicity + is_delimiting are emitted as part of
13
+ // each member's named-node object via the partitiveMemberToQuads
14
+ // helper (separate file).
20
15
  //
21
16
  // The carrying concept links via `gloss:hasPartitiveRelation`.
22
17
  //
@@ -25,7 +20,6 @@
25
20
 
26
21
  import { PRED } from './predicates.js';
27
22
  import { WELL_KNOWN } from './prefixes.js';
28
- import { deterministicBnode } from './deterministic-id.js';
29
23
  import { namedNode, literal, quad } from './terms.js';
30
24
 
31
25
  export function* partitiveRelationToQuads(relation, { parentUri, index }) {
@@ -44,20 +38,24 @@ export function* partitiveRelationToQuads(relation, { parentUri, index }) {
44
38
  for (const member of members) {
45
39
  const ref = member?.ref ?? member;
46
40
  if (!ref || (!ref.source && !ref.id)) continue;
47
- yield quad(s, namedNode(PRED.gloss.hasPartitive),
48
- namedNode(conceptRefUri(ref, parentUri)));
41
+ const memberUri = conceptRefUri(ref, parentUri);
42
+ yield quad(s, namedNode(PRED.gloss.hasPartitive), namedNode(memberUri));
43
+
44
+ // Per-member multiplicity (ISO 704:2022) and is_delimiting.
45
+ if (member?.multiplicity) {
46
+ yield quad(namedNode(memberUri), namedNode(PRED.gloss.multiplicity),
47
+ literal(member.multiplicity));
48
+ }
49
+ if (member?.is_delimiting === true) {
50
+ yield quad(namedNode(memberUri), namedNode(PRED.gloss.isDelimiting),
51
+ literal('true', 'xsd:boolean'));
52
+ }
49
53
  }
50
54
 
51
55
  if (relation.completeness) {
52
56
  yield quad(s, namedNode(PRED.gloss.completeness), literal(relation.completeness));
53
57
  }
54
58
 
55
- if (relation.plurality != null) {
56
- const pSubject = deterministicBnode(subjectUri, 'plurality', 0);
57
- yield quad(s, namedNode(PRED.gloss.hasPlurality), namedNode(pSubject));
58
- yield* pluralityToQuads(relation.plurality, pSubject);
59
- }
60
-
61
59
  if (relation.criterion && typeof relation.criterion === 'object') {
62
60
  for (const [lang, text] of Object.entries(relation.criterion)) {
63
61
  if (typeof text !== 'string') continue;
@@ -66,25 +64,6 @@ export function* partitiveRelationToQuads(relation, { parentUri, index }) {
66
64
  }
67
65
  }
68
66
 
69
- function* pluralityToQuads(plurality, subjectUri) {
70
- const s = namedNode(subjectUri);
71
- yield quad(s, namedNode(WELL_KNOWN.rdfType), namedNode(PRED.gloss.TypeSharedPlurality));
72
- yield quad(s, namedNode(PRED.gloss.isShared), literal(plurality.isShared ? 'true' : 'false', 'xsd:boolean'));
73
- if (plurality.isUncertain) {
74
- yield quad(s, namedNode(PRED.gloss.isUncertain), literal('true', 'xsd:boolean'));
75
- }
76
- if (plurality.sharedType) {
77
- // sharedType is a ConceptRef-like object; emit as a concept URI.
78
- // We don't have parentUri here, but sharedType typically points at
79
- // an external concept. Fall back to urn form.
80
- const st = plurality.sharedType;
81
- const uri = st.id
82
- ? `urn:glossarist:${st.source ?? 'unknown'}:${st.id}`
83
- : `urn:glossarist:${st.source ?? 'unknown'}:`;
84
- yield quad(s, namedNode(PRED.gloss.sharedType), namedNode(uri));
85
- }
86
- }
87
-
88
67
  // Subject URI scheme: `<base>/partitive-relation/<carrying-id>/<comprehensive-id>`.
89
68
  // Matches the Ruby emitter's scheme. Falls back to an index suffix if
90
69
  // the comprehensive has no id, so two relations on the same concept
@@ -107,16 +107,12 @@ export declare const PRED = {
107
107
  "hyperedgeContent": "https://www.glossarist.org/ontologies/hyperedgeContent",
108
108
  "PartitiveRelation": "https://www.glossarist.org/ontologies/PartitiveRelation",
109
109
  "PartitiveMember": "https://www.glossarist.org/ontologies/PartitiveMember",
110
- "TypeSharedPlurality": "https://www.glossarist.org/ontologies/TypeSharedPlurality",
111
110
  "hasPartitiveRelation": "https://www.glossarist.org/ontologies/hasPartitiveRelation",
112
111
  "hasPartitive": "https://www.glossarist.org/ontologies/hasPartitive",
113
112
  "completeness": "https://www.glossarist.org/ontologies/completeness",
114
- "hasPlurality": "https://www.glossarist.org/ontologies/hasPlurality",
115
- "isShared": "https://www.glossarist.org/ontologies/isShared",
116
- "isUncertain": "https://www.glossarist.org/ontologies/isUncertain",
117
- "sharedType": "https://www.glossarist.org/ontologies/sharedType",
113
+ "multiplicity": "https://www.glossarist.org/ontologies/multiplicity",
114
+ "isDelimiting": "https://www.glossarist.org/ontologies/isDelimiting",
118
115
  "criterion": "https://www.glossarist.org/ontologies/criterion",
119
- "certainty": "https://www.glossarist.org/ontologies/certainty",
120
116
  "provides": "https://www.glossarist.org/ontologies/provides",
121
117
  "providedBy": "https://www.glossarist.org/ontologies/providedBy",
122
118
  "refType": "https://www.glossarist.org/ontologies/refType",
@@ -393,16 +389,12 @@ export type Predicate =
393
389
  | "https://www.glossarist.org/ontologies/hyperedgeContent"
394
390
  | "https://www.glossarist.org/ontologies/PartitiveRelation"
395
391
  | "https://www.glossarist.org/ontologies/PartitiveMember"
396
- | "https://www.glossarist.org/ontologies/TypeSharedPlurality"
397
392
  | "https://www.glossarist.org/ontologies/hasPartitiveRelation"
398
393
  | "https://www.glossarist.org/ontologies/hasPartitive"
399
394
  | "https://www.glossarist.org/ontologies/completeness"
400
- | "https://www.glossarist.org/ontologies/hasPlurality"
401
- | "https://www.glossarist.org/ontologies/isShared"
402
- | "https://www.glossarist.org/ontologies/isUncertain"
403
- | "https://www.glossarist.org/ontologies/sharedType"
395
+ | "https://www.glossarist.org/ontologies/multiplicity"
396
+ | "https://www.glossarist.org/ontologies/isDelimiting"
404
397
  | "https://www.glossarist.org/ontologies/criterion"
405
- | "https://www.glossarist.org/ontologies/certainty"
406
398
  | "https://www.glossarist.org/ontologies/provides"
407
399
  | "https://www.glossarist.org/ontologies/providedBy"
408
400
  | "https://www.glossarist.org/ontologies/refType"
@@ -107,16 +107,12 @@ export const PRED = {
107
107
  "hyperedgeContent": "https://www.glossarist.org/ontologies/hyperedgeContent",
108
108
  "PartitiveRelation": "https://www.glossarist.org/ontologies/PartitiveRelation",
109
109
  "PartitiveMember": "https://www.glossarist.org/ontologies/PartitiveMember",
110
- "TypeSharedPlurality": "https://www.glossarist.org/ontologies/TypeSharedPlurality",
111
110
  "hasPartitiveRelation": "https://www.glossarist.org/ontologies/hasPartitiveRelation",
112
111
  "hasPartitive": "https://www.glossarist.org/ontologies/hasPartitive",
113
112
  "completeness": "https://www.glossarist.org/ontologies/completeness",
114
- "hasPlurality": "https://www.glossarist.org/ontologies/hasPlurality",
115
- "isShared": "https://www.glossarist.org/ontologies/isShared",
116
- "isUncertain": "https://www.glossarist.org/ontologies/isUncertain",
117
- "sharedType": "https://www.glossarist.org/ontologies/sharedType",
113
+ "multiplicity": "https://www.glossarist.org/ontologies/multiplicity",
114
+ "isDelimiting": "https://www.glossarist.org/ontologies/isDelimiting",
118
115
  "criterion": "https://www.glossarist.org/ontologies/criterion",
119
- "certainty": "https://www.glossarist.org/ontologies/certainty",
120
116
  "provides": "https://www.glossarist.org/ontologies/provides",
121
117
  "providedBy": "https://www.glossarist.org/ontologies/providedBy",
122
118
  "refType": "https://www.glossarist.org/ontologies/refType",
@@ -71,19 +71,10 @@ export class PartitiveRelationCoherenceRule extends ValidationRule {
71
71
  }
72
72
  }
73
73
 
74
- // Check 4: plurality coherence (warning).
75
- for (let i = 0; i < relations.length; i++) {
76
- const plural = relations[i]?.plurality;
77
- if (!plural) continue;
78
- if (plural.isUncertain && !plural.isShared) {
79
- result.addWarning(
80
- `${path}partitiveRelations[${i}].plurality`,
81
- `plurality has isUncertain=true without isShared=true (semantically odd: ` +
82
- `ISO 704 broken line qualifies the close-set double line plurality; ` +
83
- `without double, what is being qualified?)`,
84
- );
85
- }
86
- }
74
+ // (Check 4 — plurality coherence — removed. The prior plurality
75
+ // block was based on a misreading of ISO 704; the corrected model
76
+ // uses per-member multiplicity + is_delimiting, which are validated
77
+ // at construction by PartitiveMember itself.)
87
78
  }
88
79
  }
89
80
 
@@ -1,21 +0,0 @@
1
- // MemberCertainty — per-partitive certainty for a PartitiveMember.
2
- //
3
- // Glossarist extension beyond ISO 704 notation. ISO 704's broken-line
4
- // notation marks plurality-level uncertainty; per-member certainty
5
- // lets a relation assert "member b is confirmed, member d is possible"
6
- // at the member level.
7
- //
8
- // Defaults to `confirmed` when omitted (a member with no certainty
9
- // field is implicitly confirmed).
10
-
11
- import { makeEnum } from './enum.js';
12
-
13
- export const MEMBER_CERTAINTY = makeEnum('MEMBER_CERTAINTY', {
14
- CONFIRMED: 'confirmed',
15
- POSSIBLE: 'possible',
16
- });
17
-
18
- export const MEMBER_CERTAINTY_VALUES = MEMBER_CERTAINTY.VALUES;
19
- export const isValidMemberCertainty = MEMBER_CERTAINTY.isValid;
20
-
21
- export const DEFAULT_MEMBER_CERTAINTY = MEMBER_CERTAINTY.CONFIRMED;
@@ -1,71 +0,0 @@
1
- // TypeSharedPlurality — semantic claims encoded by ISO 704's
2
- // close-set double line and broken line notation, promoted from
3
- // diagram-notation flags to structured data.
4
- //
5
- // is_shared — ISO 704 close-set double line. True when several
6
- // partitives of a given type are involved.
7
- // is_uncertain — ISO 704 broken line. True when the type-shared
8
- // plurality is uncertain (asserted to exist but its
9
- // boundaries are not firmly established).
10
- // Defaults to false when omitted.
11
- // shared_type — Glossarist extension. The type the partitives
12
- // share, when known. ISO notation does not encode
13
- // this; left for the reader to infer. Optional even
14
- // when is_shared is true.
15
- //
16
- // A PartitiveRelation has at most one TypeSharedPlurality block.
17
- // Absent means: no type-shared plurality claim is being made.
18
- //
19
- // Replaces the v1 `markers: [double, dashed]` field per
20
- // TODO.partitive-relation-v2 item 03.
21
-
22
- import { GlossaristModel } from './base.js';
23
- import { ConceptRef } from './concept-ref.js';
24
-
25
- export class TypeSharedPlurality extends GlossaristModel {
26
- constructor(data = {}) {
27
- super();
28
- if (typeof data.isShared !== 'boolean' && typeof data.is_shared !== 'boolean') {
29
- throw new Error(
30
- 'TypeSharedPlurality requires isShared (boolean); got: ' +
31
- `${JSON.stringify(data.isShared ?? data.is_shared)}`,
32
- );
33
- }
34
- this.isShared = data.isShared ?? data.is_shared;
35
- this.isUncertain = data.isUncertain ?? data.is_uncertain ?? false;
36
- this.sharedType = data.sharedType
37
- ? (data.sharedType instanceof ConceptRef ? data.sharedType : new ConceptRef(data.sharedType))
38
- : null;
39
-
40
- _validate(this);
41
- }
42
-
43
- hasSharedType() {
44
- return this.sharedType != null;
45
- }
46
-
47
- toJSON() {
48
- const obj = { is_shared: this.isShared };
49
- if (this.isUncertain) obj.is_uncertain = this.isUncertain;
50
- if (this.sharedType != null) obj.shared_type = this.sharedType.toJSON();
51
- return obj;
52
- }
53
-
54
- static fromJSON(data) {
55
- return new TypeSharedPlurality(data);
56
- }
57
- }
58
-
59
- function _validate(plurality) {
60
- if (typeof plurality.isShared !== 'boolean') {
61
- throw new Error('TypeSharedPlurality.isShared must be boolean');
62
- }
63
- if (typeof plurality.isUncertain !== 'boolean') {
64
- throw new Error('TypeSharedPlurality.isUncertain must be boolean');
65
- }
66
- // ISO 704 semantic check: a broken line qualifies the close-set
67
- // double-line plurality claim. is_uncertain without is_shared is
68
- // semantically odd. The model accepts it (data is data); the
69
- // PartitiveRelationCoherenceRule surfaces it as a warning so
70
- // reviewers can decide whether the data shape is intentional.
71
- }