@primmel/primmel 1.5.0 → 1.5.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.
Files changed (112) hide show
  1. package/dist/src/check-rules.d.ts.map +1 -1
  2. package/dist/src/check-rules.js +7 -1
  3. package/dist/src/check-rules.js.map +1 -1
  4. package/dist/src/check.d.ts +13 -0
  5. package/dist/src/check.d.ts.map +1 -1
  6. package/dist/src/check.js +91 -0
  7. package/dist/src/check.js.map +1 -1
  8. package/dist/src/ser-des/config/artifact.d.ts.map +1 -1
  9. package/dist/src/ser-des/config/artifact.js +29 -12
  10. package/dist/src/ser-des/config/artifact.js.map +1 -1
  11. package/dist/src/ser-des/config/calculation.d.ts.map +1 -1
  12. package/dist/src/ser-des/config/calculation.js +21 -6
  13. package/dist/src/ser-des/config/calculation.js.map +1 -1
  14. package/dist/src/ser-des/config/competenceKind.d.ts.map +1 -1
  15. package/dist/src/ser-des/config/competenceKind.js +9 -0
  16. package/dist/src/ser-des/config/competenceKind.js.map +1 -1
  17. package/dist/src/ser-des/config/conformanceClass.d.ts.map +1 -1
  18. package/dist/src/ser-des/config/conformanceClass.js +2 -1
  19. package/dist/src/ser-des/config/conformanceClass.js.map +1 -1
  20. package/dist/src/ser-des/config/conformanceTest.d.ts.map +1 -1
  21. package/dist/src/ser-des/config/conformanceTest.js +11 -23
  22. package/dist/src/ser-des/config/conformanceTest.js.map +1 -1
  23. package/dist/src/ser-des/config/constraint.d.ts.map +1 -1
  24. package/dist/src/ser-des/config/constraint.js +9 -0
  25. package/dist/src/ser-des/config/constraint.js.map +1 -1
  26. package/dist/src/ser-des/config/field-parser.d.ts.map +1 -1
  27. package/dist/src/ser-des/config/field-parser.js +29 -2
  28. package/dist/src/ser-des/config/field-parser.js.map +1 -1
  29. package/dist/src/ser-des/config/form.d.ts.map +1 -1
  30. package/dist/src/ser-des/config/form.js +12 -2
  31. package/dist/src/ser-des/config/form.js.map +1 -1
  32. package/dist/src/ser-des/config/formulasUsed.d.ts.map +1 -1
  33. package/dist/src/ser-des/config/formulasUsed.js +20 -9
  34. package/dist/src/ser-des/config/formulasUsed.js.map +1 -1
  35. package/dist/src/ser-des/config/packageManifest.d.ts.map +1 -1
  36. package/dist/src/ser-des/config/packageManifest.js +5 -2
  37. package/dist/src/ser-des/config/packageManifest.js.map +1 -1
  38. package/dist/src/ser-des/config/process.d.ts.map +1 -1
  39. package/dist/src/ser-des/config/process.js +15 -12
  40. package/dist/src/ser-des/config/process.js.map +1 -1
  41. package/dist/src/ser-des/config/ref.d.ts +55 -0
  42. package/dist/src/ser-des/config/ref.d.ts.map +1 -1
  43. package/dist/src/ser-des/config/ref.js +115 -0
  44. package/dist/src/ser-des/config/ref.js.map +1 -1
  45. package/dist/src/ser-des/config/referenceMaterial.d.ts.map +1 -1
  46. package/dist/src/ser-des/config/referenceMaterial.js +43 -19
  47. package/dist/src/ser-des/config/referenceMaterial.js.map +1 -1
  48. package/dist/src/ser-des/config/requirement.d.ts.map +1 -1
  49. package/dist/src/ser-des/config/requirement.js +9 -13
  50. package/dist/src/ser-des/config/requirement.js.map +1 -1
  51. package/dist/src/ser-des/config/subject.d.ts.map +1 -1
  52. package/dist/src/ser-des/config/subject.js +160 -21
  53. package/dist/src/ser-des/config/subject.js.map +1 -1
  54. package/dist/src/ser-des/config/symbol.d.ts.map +1 -1
  55. package/dist/src/ser-des/config/symbol.js +10 -1
  56. package/dist/src/ser-des/config/symbol.js.map +1 -1
  57. package/dist/src/ser-des/config/table.d.ts.map +1 -1
  58. package/dist/src/ser-des/config/table.js +10 -8
  59. package/dist/src/ser-des/config/table.js.map +1 -1
  60. package/dist/src/ser-des/config/term.d.ts.map +1 -1
  61. package/dist/src/ser-des/config/term.js +18 -1
  62. package/dist/src/ser-des/config/term.js.map +1 -1
  63. package/dist/src/ser-des/config/testPointSet.d.ts.map +1 -1
  64. package/dist/src/ser-des/config/testPointSet.js +24 -13
  65. package/dist/src/ser-des/config/testPointSet.js.map +1 -1
  66. package/dist/src/ser-des/config/testSequence.d.ts.map +1 -1
  67. package/dist/src/ser-des/config/testSequence.js +19 -7
  68. package/dist/src/ser-des/config/testSequence.js.map +1 -1
  69. package/dist/src/ser-des/config/verdict.d.ts.map +1 -1
  70. package/dist/src/ser-des/config/verdict.js +24 -13
  71. package/dist/src/ser-des/config/verdict.js.map +1 -1
  72. package/dist/src/ser-des/parse-block.d.ts +16 -5
  73. package/dist/src/ser-des/parse-block.d.ts.map +1 -1
  74. package/dist/src/ser-des/parse-block.js +45 -6
  75. package/dist/src/ser-des/parse-block.js.map +1 -1
  76. package/dist/src/types/Artifact.d.ts +6 -0
  77. package/dist/src/types/Artifact.d.ts.map +1 -1
  78. package/dist/src/types/Calculation.d.ts +2 -0
  79. package/dist/src/types/Calculation.d.ts.map +1 -1
  80. package/dist/src/types/CompetenceKind.d.ts +3 -0
  81. package/dist/src/types/CompetenceKind.d.ts.map +1 -1
  82. package/dist/src/types/Constraint.d.ts +3 -0
  83. package/dist/src/types/Constraint.d.ts.map +1 -1
  84. package/dist/src/types/Form.d.ts +3 -0
  85. package/dist/src/types/Form.d.ts.map +1 -1
  86. package/dist/src/types/FormulasUsed.d.ts +2 -0
  87. package/dist/src/types/FormulasUsed.d.ts.map +1 -1
  88. package/dist/src/types/Invariant.d.ts +1 -0
  89. package/dist/src/types/Invariant.d.ts.map +1 -1
  90. package/dist/src/types/ReferenceMaterial.d.ts +7 -0
  91. package/dist/src/types/ReferenceMaterial.d.ts.map +1 -1
  92. package/dist/src/types/Subject.d.ts +22 -0
  93. package/dist/src/types/Subject.d.ts.map +1 -1
  94. package/dist/src/types/Symbol.d.ts +4 -0
  95. package/dist/src/types/Symbol.d.ts.map +1 -1
  96. package/dist/src/types/Table.d.ts +4 -0
  97. package/dist/src/types/Table.d.ts.map +1 -1
  98. package/dist/src/types/Term.d.ts +2 -0
  99. package/dist/src/types/Term.d.ts.map +1 -1
  100. package/dist/src/types/TestPointSet.d.ts +4 -0
  101. package/dist/src/types/TestPointSet.d.ts.map +1 -1
  102. package/dist/src/types/TestSequence.d.ts +2 -0
  103. package/dist/src/types/TestSequence.d.ts.map +1 -1
  104. package/dist/src/types/Verdict.d.ts +4 -0
  105. package/dist/src/types/Verdict.d.ts.map +1 -1
  106. package/dist/src/types/process.d.ts +3 -0
  107. package/dist/src/types/process.d.ts.map +1 -1
  108. package/dist/src/validate.js +9 -1
  109. package/dist/src/validate.js.map +1 -1
  110. package/dist-browser/index.mjs +1587 -1348
  111. package/dist-cli/primmel.mjs +566 -124
  112. package/package.json +1 -1
@@ -389,11 +389,39 @@ function forEachEntry(data, visitor, errCtx) {
389
389
  `Parsing error: ${errCtx.construct}. ID ${errCtx.id}: Expecting value for ${keyword}`
390
390
  );
391
391
  }
392
- const claimed = visitor(keyword, () => t[i++]);
392
+ const claimed = visitor(
393
+ keyword,
394
+ () => t[i++],
395
+ () => t[i]
396
+ );
393
397
  if (!claimed) {
398
+ if (keyword === "ref") {
399
+ i++;
400
+ i++;
401
+ if (i < t.length && t[i].startsWith("{")) {
402
+ i++;
403
+ }
404
+ } else {
405
+ i++;
406
+ }
407
+ }
408
+ }
409
+ }
410
+ function skipUnknownValue(t, i, keyword) {
411
+ if (keyword === "ref") {
412
+ i++;
413
+ if (i < t.length) {
394
414
  i++;
395
415
  }
416
+ if (i < t.length && t[i].startsWith("{")) {
417
+ i++;
418
+ }
419
+ return i;
420
+ }
421
+ if (i < t.length) {
422
+ i++;
396
423
  }
424
+ return i;
397
425
  }
398
426
  function forEachAttribute(data, visitor, errCtx) {
399
427
  if (data === "") {
@@ -1080,6 +1108,119 @@ var parseMetadata = function(token) {
1080
1108
  };
1081
1109
  };
1082
1110
 
1111
+ // src/ser-des/config/ref.ts
1112
+ function parseRef(t, i, stripWrapping2, unwrapBlock2) {
1113
+ const predicate = stripWrapping2(t[i++] ?? "");
1114
+ const target = stripWrapping2(t[i++] ?? "");
1115
+ const ref = { predicate, target };
1116
+ if (i < t.length && t[i].startsWith("{")) {
1117
+ const block = unwrapBlock2(t[i++]);
1118
+ const m = /note\s+"([^"]*)"/.exec(block) ?? /note\s+(\S+)/.exec(block);
1119
+ if (m) {
1120
+ ref.note = m[1];
1121
+ }
1122
+ }
1123
+ return { ref, next: i };
1124
+ }
1125
+ function parseRefFromReaders(value, peek, stripWrapping2, unwrapBlock2) {
1126
+ const parts = [value(), value()];
1127
+ const next = peek();
1128
+ if (next && next.startsWith("{")) {
1129
+ parts.push(value());
1130
+ }
1131
+ return parseRef(parts, 0, stripWrapping2, unwrapBlock2).ref;
1132
+ }
1133
+ function dumpRefs(refs, indent, escapeString2) {
1134
+ if (!refs || refs.length === 0) {
1135
+ return "";
1136
+ }
1137
+ let out = "";
1138
+ for (const r of refs) {
1139
+ out += `${indent}ref ${r.predicate} "${escapeString2(r.target)}"`;
1140
+ out += r.note ? ` {
1141
+ ${indent} note "${escapeString2(r.note)}"
1142
+ ${indent}}
1143
+ ` : "\n";
1144
+ }
1145
+ return out;
1146
+ }
1147
+ function refTargetToSourceRef(target) {
1148
+ const m = /^(urn:[^#]+)(?:#(.+))?$/.exec(target);
1149
+ if (!m) {
1150
+ return null;
1151
+ }
1152
+ const anchor = m[2];
1153
+ if (!anchor) {
1154
+ return { doc: target, clause: "" };
1155
+ }
1156
+ if (anchor.startsWith("clause-")) {
1157
+ const rest = anchor.slice("clause-".length);
1158
+ const slash = rest.indexOf("/");
1159
+ if (slash >= 0) {
1160
+ return {
1161
+ doc: m[1],
1162
+ clause: rest.slice(0, slash),
1163
+ fragment: rest.slice(slash + 1)
1164
+ };
1165
+ }
1166
+ return { doc: m[1], clause: rest };
1167
+ }
1168
+ return { doc: target, clause: "" };
1169
+ }
1170
+ function foldRefIntoLegacy(el, ref) {
1171
+ if (ref.predicate === "derives-from") {
1172
+ const b = refTargetToSourceRef(ref.target);
1173
+ if (!b) {
1174
+ return false;
1175
+ }
1176
+ (el.sourceRefs ??= []).push(b);
1177
+ if ("source" in el && !el.source) {
1178
+ el.source = b;
1179
+ }
1180
+ if ("sourceRef" in el && !el.sourceRef) {
1181
+ el.sourceRef = b;
1182
+ }
1183
+ if ("reference" in el && !el.reference) {
1184
+ el.reference = b.doc;
1185
+ }
1186
+ return true;
1187
+ }
1188
+ if (ref.predicate === "cites") {
1189
+ if (el.referenceIds) {
1190
+ el.referenceIds.push(ref.target);
1191
+ } else if (el.fieldReferences) {
1192
+ el.fieldReferences.push({ urn: ref.target, role: "reference" });
1193
+ } else if (el.formReferences) {
1194
+ el.formReferences.push({ urn: ref.target, role: "reference" });
1195
+ }
1196
+ return true;
1197
+ }
1198
+ const CITATION_ROLES = [
1199
+ "requirement",
1200
+ "test-procedure",
1201
+ "calculation",
1202
+ "report-format",
1203
+ "method"
1204
+ ];
1205
+ if (CITATION_ROLES.includes(ref.predicate)) {
1206
+ const channel = el.fieldReferences ?? el.formReferences;
1207
+ if (!channel) {
1208
+ return false;
1209
+ }
1210
+ channel.push({ urn: ref.target, role: ref.predicate });
1211
+ return true;
1212
+ }
1213
+ return false;
1214
+ }
1215
+ function dumpSourceRefAsRef(src, indent, escapeString2) {
1216
+ if (src.doc && src.doc.startsWith("urn:")) {
1217
+ const anchor = `${src.doc}${src.clause ? "#clause-" + src.clause : ""}${src.fragment ? "/" + src.fragment : ""}`;
1218
+ return `${indent}ref derives-from "${escapeString2(anchor)}"
1219
+ `;
1220
+ }
1221
+ return `${indent}source { doc "${escapeString2(src.doc ?? "")}" clause "${escapeString2(String(src.clause ?? ""))}"` + (src.fragment ? ` fragment "${escapeString2(src.fragment)}"` : "") + " }\n";
1222
+ }
1223
+
1083
1224
  // src/ser-des/config/series.ts
1084
1225
  function parseSeriesDecl(block) {
1085
1226
  const decl = { axes: [], cellSymbol: "", cellUnit: "" };
@@ -1168,21 +1309,6 @@ function dumpSeriesDecl(decl) {
1168
1309
  return out;
1169
1310
  }
1170
1311
 
1171
- // src/ser-des/config/ref.ts
1172
- function parseRef(t, i, stripWrapping2, unwrapBlock2) {
1173
- const predicate = stripWrapping2(t[i++] ?? "");
1174
- const target = stripWrapping2(t[i++] ?? "");
1175
- const ref = { predicate, target };
1176
- if (i < t.length && t[i].startsWith("{")) {
1177
- const block = unwrapBlock2(t[i++]);
1178
- const m = /note\s+"([^"]*)"/.exec(block) ?? /note\s+(\S+)/.exec(block);
1179
- if (m) {
1180
- ref.note = m[1];
1181
- }
1182
- }
1183
- return { ref, next: i };
1184
- }
1185
-
1186
1312
  // src/ser-des/config/sourceDiscrepancy.ts
1187
1313
  var VALID_RESOLUTIONS = ["follows_clause_x", "annotated_only"];
1188
1314
  function parseSourceDiscrepancy(block) {
@@ -1499,7 +1625,9 @@ function parseFormField(name, block, type) {
1499
1625
  field.fieldReferences = parseRoleReferences(unwrapBlock(t[i++]));
1500
1626
  } else if (cmd === "ref") {
1501
1627
  const r = parseRef(t, i, stripWrapping, unwrapBlock);
1502
- field.refs.push(r.ref);
1628
+ if (!foldRefIntoLegacy(field, r.ref)) {
1629
+ field.refs.push(r.ref);
1630
+ }
1503
1631
  i = r.next;
1504
1632
  } else if (cmd === "specification_reference") {
1505
1633
  field.specificationReference = stripWrapping(t[i++]);
@@ -1830,10 +1958,17 @@ function dumpFormField(field, indent) {
1830
1958
  if (field.targets.length > 0) {
1831
1959
  inner.push("targets { " + field.targets.join(" ") + " }");
1832
1960
  }
1961
+ if (field.sourceRefs && field.sourceRefs.length > 0) {
1962
+ for (const s of field.sourceRefs) {
1963
+ inner.push(dumpSourceRefAsRef(s, "", escapeString).trimEnd());
1964
+ }
1965
+ }
1833
1966
  if (field.fieldReferences.length > 0) {
1834
- inner.push(
1835
- "references { " + dumpRoleReferences(field.fieldReferences) + " }"
1836
- );
1967
+ for (const r of field.fieldReferences) {
1968
+ inner.push(
1969
+ "ref " + roleToPredicateForDump(r.role) + ' "' + escapeString(r.urn) + '"'
1970
+ );
1971
+ }
1837
1972
  }
1838
1973
  if (field.refs && field.refs.length > 0) {
1839
1974
  for (const r of field.refs) {
@@ -1908,19 +2043,14 @@ function parseRoleReferences(block) {
1908
2043
  }
1909
2044
  return out;
1910
2045
  }
1911
- function dumpRoleReferences(refs) {
1912
- const roles = [];
1913
- const byRole = /* @__PURE__ */ new Map();
1914
- for (const r of refs) {
1915
- if (!byRole.has(r.role)) {
1916
- byRole.set(r.role, []);
1917
- roles.push(r.role);
1918
- }
1919
- byRole.get(r.role).push(r.urn);
2046
+ function roleToPredicateForDump(role) {
2047
+ if (role === "source") {
2048
+ return "derives-from";
1920
2049
  }
1921
- return roles.map(
1922
- (role) => role + " { " + byRole.get(role).map((u) => '"' + escapeString(u) + '"').join(" ") + " }"
1923
- ).join(" ");
2050
+ if (role === "reference") {
2051
+ return "cites";
2052
+ }
2053
+ return role;
1924
2054
  }
1925
2055
 
1926
2056
  // src/ser-des/config/quantity.ts
@@ -2220,7 +2350,7 @@ function parseProcessInstances(block) {
2220
2350
  }
2221
2351
  }
2222
2352
  } else {
2223
- unwrapBlock(t[i++]);
2353
+ i = skipUnknownValue(t, i, cmd);
2224
2354
  }
2225
2355
  }
2226
2356
  return out;
@@ -2468,7 +2598,7 @@ var parseProcess = function(id, data) {
2468
2598
  }
2469
2599
  forEachEntry(
2470
2600
  data,
2471
- (keyword, value) => {
2601
+ (keyword, value, peek) => {
2472
2602
  if (keyword === "modality") {
2473
2603
  result.modality = value();
2474
2604
  } else if (keyword === "name") {
@@ -2537,6 +2667,11 @@ var parseProcess = function(id, data) {
2537
2667
  result.source = src;
2538
2668
  }
2539
2669
  (result.sourceRefs ??= []).push(src);
2670
+ } else if (keyword === "ref") {
2671
+ const r = parseRefFromReaders(value, peek, stripWrapping, unwrapBlock);
2672
+ if (!foldRefIntoLegacy(result, r)) {
2673
+ (result.refs ??= []).push(r);
2674
+ }
2540
2675
  } else {
2541
2676
  return false;
2542
2677
  }
@@ -2801,8 +2936,9 @@ var dumpProcess = function(process2, ctx) {
2801
2936
  out += dumpDoes(process2.does);
2802
2937
  }
2803
2938
  for (const src of process2.sourceRefs ?? (process2.source && (process2.source.doc || process2.source.clause) ? [process2.source] : [])) {
2804
- out += ' source { doc "' + escapeString(src.doc) + '" clause "' + escapeString(src.clause) + '"' + (src.fragment ? ' fragment "' + escapeString(src.fragment) + '"' : "") + " }\n";
2939
+ out += dumpSourceRefAsRef(src, " ", escapeString);
2805
2940
  }
2941
+ out += dumpRefs(process2.refs, " ", escapeString);
2806
2942
  if (process2.parent && (process2.children.length === 0 || !ctx?.nested)) {
2807
2943
  out += " parent " + process2.parent + "\n";
2808
2944
  }
@@ -3544,6 +3680,12 @@ var parseTable = function(id, data) {
3544
3680
  } else if (command === "data") {
3545
3681
  const dataBlock = unwrapBlock(t[i++]);
3546
3682
  result.data = parseTableData(dataBlock);
3683
+ } else if (command === "ref") {
3684
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
3685
+ if (!foldRefIntoLegacy(result, rr.ref)) {
3686
+ (result.refs ??= []).push(rr.ref);
3687
+ }
3688
+ i = rr.next;
3547
3689
  } else {
3548
3690
  i++;
3549
3691
  }
@@ -3611,7 +3753,7 @@ var dumpTable = function(t) {
3611
3753
  out += ' display "' + t.display + '"\n';
3612
3754
  }
3613
3755
  for (const src of t.sourceRefs ?? (t.sourceRef && (t.sourceRef.doc || t.sourceRef.clause) ? [t.sourceRef] : [])) {
3614
- out += ' source { doc "' + escapeString(src.doc) + '" clause "' + escapeString(src.clause) + '"' + (src.fragment ? ' fragment "' + escapeString(src.fragment) + '"' : "") + " }\n";
3756
+ out += dumpSourceRefAsRef(src, " ", escapeString);
3615
3757
  }
3616
3758
  if (t.sourceDiscrepancy) {
3617
3759
  out += dumpSourceDiscrepancy(t.sourceDiscrepancy, " ") + "\n";
@@ -4134,7 +4276,9 @@ var parseForm = function(id, data) {
4134
4276
  result.formReferences = parseRoleReferences(unwrapBlock(t[i++]));
4135
4277
  } else if (command === "ref") {
4136
4278
  const r = parseRef(t, i, stripWrapping, unwrapBlock);
4137
- result.refs = [...result.refs ?? [], r.ref];
4279
+ if (!foldRefIntoLegacy(result, r.ref)) {
4280
+ result.refs = [...result.refs ?? [], r.ref];
4281
+ }
4138
4282
  i = r.next;
4139
4283
  } else if (command === "calculation_context") {
4140
4284
  result.calculationContext = parseCalculationContext(
@@ -4418,7 +4562,10 @@ var dumpForm = function(f) {
4418
4562
  out += " report_rows { field " + f.reportRows.field + " item_key " + f.reportRows.itemKey + " }\n";
4419
4563
  }
4420
4564
  if (f.formReferences.length > 0) {
4421
- out += " references { " + dumpRoleReferences(f.formReferences) + " }\n";
4565
+ for (const r of f.formReferences) {
4566
+ const pred = r.role === "source" ? "derives-from" : r.role === "reference" ? "cites" : r.role;
4567
+ out += " ref " + pred + ' "' + escapeString(r.urn) + '"\n';
4568
+ }
4422
4569
  }
4423
4570
  if (f.refs && f.refs.length > 0) {
4424
4571
  for (const r of f.refs) {
@@ -4689,7 +4836,14 @@ var parseSymbol = function(id, data) {
4689
4836
  };
4690
4837
  forEachEntry(
4691
4838
  data,
4692
- (command, value) => {
4839
+ (command, value, peek) => {
4840
+ if (command === "ref") {
4841
+ const r = parseRefFromReaders(value, peek, stripWrapping, unwrapBlock);
4842
+ if (!foldRefIntoLegacy(result, r)) {
4843
+ (result.refs ??= []).push(r);
4844
+ }
4845
+ return true;
4846
+ }
4693
4847
  if (command === "name") {
4694
4848
  result.name = unwrapped(value);
4695
4849
  } else if (command === "definition") {
@@ -4859,7 +5013,11 @@ var parseCalculation = function(id, data) {
4859
5013
  ref: [],
4860
5014
  _relations: {
4861
5015
  ref: []
4862
- }
5016
+ },
5017
+ // Initialized so the ref fold (docs/primmel/18 §18.4) mirrors the
5018
+ // first derives-from block here — the fold only mirrors slots the
5019
+ // object already carries.
5020
+ sourceRef: null
4863
5021
  };
4864
5022
  if (data !== "") {
4865
5023
  const t = tokenizePackage(data);
@@ -4883,6 +5041,12 @@ var parseCalculation = function(id, data) {
4883
5041
  result.expression = unwrapBlock(t[i++]);
4884
5042
  } else if (command === "reference") {
4885
5043
  result._relations.ref = tokenizePackage(t[i++]);
5044
+ } else if (command === "ref") {
5045
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
5046
+ if (!foldRefIntoLegacy(result, rr.ref)) {
5047
+ (result.refs ??= []).push(rr.ref);
5048
+ }
5049
+ i = rr.next;
4886
5050
  } else if (command === "source") {
4887
5051
  const inner = tokenize(unwrapBlock(t[i++]));
4888
5052
  const src = {
@@ -5149,7 +5313,10 @@ var dumpCalculation = function(c) {
5149
5313
  out += " profile " + c.profile + "\n";
5150
5314
  }
5151
5315
  for (const src of c.sourceRefs ?? (c.sourceRef && (c.sourceRef.doc || c.sourceRef.clause) ? [c.sourceRef] : [])) {
5152
- out += ' source { doc "' + escapeString(src.doc) + '" clause "' + escapeString(src.clause) + '"' + (src.fragment ? ' fragment "' + escapeString(src.fragment) + '"' : "") + " }\n";
5316
+ out += dumpSourceRefAsRef(src, " ", escapeString);
5317
+ }
5318
+ for (const r of c.refs ?? []) {
5319
+ out += " ref " + r.predicate + ' "' + escapeString(r.target) + '"' + (r.note ? ' { note "' + escapeString(r.note) + '" }' : "") + "\n";
5153
5320
  }
5154
5321
  if (c.ref.length > 0) {
5155
5322
  out += " reference {\n";
@@ -6430,6 +6597,12 @@ var parseCompetenceKind = function(id, data) {
6430
6597
  );
6431
6598
  }
6432
6599
  result.methodStandards.push({ id: stdId, title: readValue(t[i++]) });
6600
+ } else if (keyword === "ref") {
6601
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
6602
+ if (!foldRefIntoLegacy(result, rr.ref)) {
6603
+ (result.refs ??= []).push(rr.ref);
6604
+ }
6605
+ i = rr.next;
6433
6606
  } else {
6434
6607
  i++;
6435
6608
  }
@@ -6834,11 +7007,15 @@ var parseConformanceTest = function(id, data) {
6834
7007
  inheritsFrom: "",
6835
7008
  resultForms: [],
6836
7009
  derivedValues: [],
6837
- sourceDiscrepancy: null
7010
+ sourceDiscrepancy: null,
7011
+ // The singular provenance slot is initialized so the ref fold
7012
+ // (docs/primmel/18 §18.4) mirrors the first derives-from block into
7013
+ // it — the fold only mirrors slots the object already carries.
7014
+ sourceRef: null
6838
7015
  };
6839
7016
  forEachEntry(
6840
7017
  data,
6841
- (keyword, value) => {
7018
+ (keyword, value, peek) => {
6842
7019
  if (keyword === "name") {
6843
7020
  result.name = unwrapped(value);
6844
7021
  } else if (keyword === "purpose") {
@@ -6889,10 +7066,10 @@ var parseConformanceTest = function(id, data) {
6889
7066
  } else if (keyword === "targets") {
6890
7067
  result.targets = tokenizePackage(value());
6891
7068
  } else if (keyword === "ref") {
6892
- const block = value();
6893
- const rt = tokenizePackage(block);
6894
- const rr = parseRef(rt, 0, stripWrapping, unwrapBlock);
6895
- (result.refs ??= []).push(rr.ref);
7069
+ const rr = parseRefFromReaders(value, peek, stripWrapping, unwrapBlock);
7070
+ if (!foldRefIntoLegacy(result, rr)) {
7071
+ (result.refs ??= []).push(rr);
7072
+ }
6896
7073
  } else if (keyword === "binds_to") {
6897
7074
  result.bindsTo = tokenizePackage(value());
6898
7075
  } else if (keyword === "applicability") {
@@ -7012,10 +7189,10 @@ var dumpConformanceTest = function(ct) {
7012
7189
  }
7013
7190
  if (ct.sourceRefs && ct.sourceRefs.length > 0) {
7014
7191
  for (const src of ct.sourceRefs) {
7015
- out += ' reference { doc "' + escapeString(src.doc) + '" clause "' + escapeString(src.clause) + '"' + (src.fragment ? ' fragment "' + escapeString(src.fragment) + '"' : "") + " }\n";
7192
+ out += dumpSourceRefAsRef(src, " ", escapeString);
7016
7193
  }
7017
7194
  } else if (ct.sourceRef && ct.sourceRef.doc) {
7018
- out += ' reference { doc "' + escapeString(ct.sourceRef.doc) + '" clause "' + escapeString(ct.sourceRef.clause) + '"' + (ct.sourceRef.fragment ? ' fragment "' + escapeString(ct.sourceRef.fragment) + '"' : "") + " }\n";
7195
+ out += dumpSourceRefAsRef(ct.sourceRef, " ", escapeString);
7019
7196
  } else if (ct.reference) {
7020
7197
  out += " reference " + ct.reference + "\n";
7021
7198
  }
@@ -7267,7 +7444,18 @@ var parseTerm = function(id, data) {
7267
7444
  };
7268
7445
  forEachEntry(
7269
7446
  data,
7270
- (command, value) => {
7447
+ (command, value, peek) => {
7448
+ if (command === "ref") {
7449
+ const r = parseRefFromReaders(value, peek, stripWrapping, unwrapBlock);
7450
+ if (r.predicate === "derives-from" && !result.source) {
7451
+ result.source = r.target;
7452
+ } else if (r.predicate === "cites") {
7453
+ result.referenceIds.push(r.target);
7454
+ } else {
7455
+ (result.refs ??= []).push(r);
7456
+ }
7457
+ return true;
7458
+ }
7271
7459
  if (command === "label") {
7272
7460
  result.label = unwrapped(value);
7273
7461
  } else if (command === "definition") {
@@ -7413,7 +7601,7 @@ var parseVerdict = function(id, data) {
7413
7601
  };
7414
7602
  forEachEntry(
7415
7603
  data,
7416
- (keyword, value) => {
7604
+ (keyword, value, peek) => {
7417
7605
  if (keyword === "quantity") {
7418
7606
  const qt = tokenize(unwrapBlock(value()));
7419
7607
  let j = 0;
@@ -7451,7 +7639,16 @@ var parseVerdict = function(id, data) {
7451
7639
  } else if (keyword === "acceptance") {
7452
7640
  result.acceptance = parseAcceptance(unwrapBlock(value()));
7453
7641
  } else if (keyword === "source" || keyword === "reference") {
7454
- result.source = readSource(unwrapBlock(value()));
7642
+ const src = readSource(unwrapBlock(value()));
7643
+ (result.sourceRefs ??= []).push(src);
7644
+ if (!result.source) {
7645
+ result.source = src;
7646
+ }
7647
+ } else if (keyword === "ref") {
7648
+ const r = parseRefFromReaders(value, peek, stripWrapping, unwrapBlock);
7649
+ if (!foldRefIntoLegacy(result, r)) {
7650
+ (result.refs ??= []).push(r);
7651
+ }
7455
7652
  } else {
7456
7653
  return false;
7457
7654
  }
@@ -7491,9 +7688,11 @@ var dumpVerdict = function(v) {
7491
7688
  if (v.acceptance) {
7492
7689
  out += dumpAcceptance(v.acceptance, " ") + "\n";
7493
7690
  }
7494
- if (v.source && (v.source.doc || v.source.clause)) {
7495
- out += ' source { doc "' + escapeString(v.source.doc) + '" clause "' + escapeString(v.source.clause) + '"' + (v.source.fragment ? ' fragment "' + escapeString(v.source.fragment) + '"' : "") + " }\n";
7691
+ const verdictSources = v.sourceRefs && v.sourceRefs.length > 0 ? v.sourceRefs : v.source && (v.source.doc || v.source.clause) ? [v.source] : [];
7692
+ for (const s of verdictSources) {
7693
+ out += dumpSourceRefAsRef(s, " ", escapeString);
7496
7694
  }
7695
+ out += dumpRefs(v.refs, " ", escapeString);
7497
7696
  out += "}\n";
7498
7697
  return out;
7499
7698
  };
@@ -7535,7 +7734,7 @@ function parseIdentityFields(block) {
7535
7734
  } else if (fc === "required") {
7536
7735
  field.required = stripWrapping(ft[j++]) === "true";
7537
7736
  } else {
7538
- unwrapBlock(ft[j++]);
7737
+ j = skipUnknownValue(ft, j, fc);
7539
7738
  }
7540
7739
  }
7541
7740
  }
@@ -7615,8 +7814,17 @@ function parseConstraints(block) {
7615
7814
  c.onViolation = stripWrapping(ct[j++]);
7616
7815
  } else if (cc === "source") {
7617
7816
  c.source = readSource(unwrapBlock(ct[j++]));
7817
+ } else if (cc === "ref") {
7818
+ const rr = parseRef(ct, j, stripWrapping, unwrapBlock);
7819
+ j = rr.next;
7820
+ if (rr.ref.predicate === "derives-from" && !c.source) {
7821
+ const b = refTargetToSourceRef(rr.ref.target);
7822
+ if (b) {
7823
+ c.source = b;
7824
+ }
7825
+ }
7618
7826
  } else {
7619
- unwrapBlock(ct[j++]);
7827
+ j = skipUnknownValue(ct, j, cc);
7620
7828
  }
7621
7829
  }
7622
7830
  }
@@ -7636,7 +7844,7 @@ var parseReferenceMaterial = function(id, data) {
7636
7844
  };
7637
7845
  forEachEntry(
7638
7846
  data,
7639
- (keyword, value) => {
7847
+ (keyword, value, peek) => {
7640
7848
  if (keyword === "kind") {
7641
7849
  result.kind = stripWrapping(value());
7642
7850
  } else if (keyword === "name") {
@@ -7644,7 +7852,16 @@ var parseReferenceMaterial = function(id, data) {
7644
7852
  } else if (keyword === "definition") {
7645
7853
  result.definition = unwrapped(value);
7646
7854
  } else if (keyword === "source") {
7647
- result.source = readSource(unwrapBlock(value()));
7855
+ const src = readSource(unwrapBlock(value()));
7856
+ (result.sourceRefs ??= []).push(src);
7857
+ if (!result.source) {
7858
+ result.source = src;
7859
+ }
7860
+ } else if (keyword === "ref") {
7861
+ const r = parseRefFromReaders(value, peek, stripWrapping, unwrapBlock);
7862
+ if (!foldRefIntoLegacy(result, r)) {
7863
+ (result.refs ??= []).push(r);
7864
+ }
7648
7865
  } else if (keyword === "identity_fields") {
7649
7866
  result.identityFields = parseIdentityFields(unwrapBlock(value()));
7650
7867
  } else if (keyword === "constraints") {
@@ -7661,12 +7878,6 @@ var parseReferenceMaterial = function(id, data) {
7661
7878
  return ctx;
7662
7879
  };
7663
7880
  };
7664
- function dumpSource(src, indent) {
7665
- if (!src || !src.doc && !src.clause) {
7666
- return "";
7667
- }
7668
- return indent + 'source { doc "' + escapeString(src.doc) + '" clause "' + escapeString(src.clause) + '"' + (src.fragment ? ' fragment "' + escapeString(src.fragment) + '"' : "") + " }\n";
7669
- }
7670
7881
  var dumpReferenceMaterial = function(m) {
7671
7882
  let out = "reference_material " + m.id + " {\n";
7672
7883
  if (m.kind) {
@@ -7678,7 +7889,11 @@ var dumpReferenceMaterial = function(m) {
7678
7889
  if (m.definition) {
7679
7890
  out += ' definition "' + escapeString(m.definition) + '"\n';
7680
7891
  }
7681
- out += dumpSource(m.source, " ");
7892
+ const rmSources = m.sourceRefs && m.sourceRefs.length > 0 ? m.sourceRefs : m.source ? [m.source] : [];
7893
+ for (const s of rmSources) {
7894
+ out += dumpSourceRefAsRef(s, " ", escapeString);
7895
+ }
7896
+ out += dumpRefs(m.refs, " ", escapeString);
7682
7897
  if (m.identityFields.length > 0) {
7683
7898
  out += " identity_fields {\n";
7684
7899
  for (const f of m.identityFields) {
@@ -7724,7 +7939,9 @@ var dumpReferenceMaterial = function(m) {
7724
7939
  if (c.onViolation) {
7725
7940
  out += " on_violation " + c.onViolation + "\n";
7726
7941
  }
7727
- out += dumpSource(c.source, " ");
7942
+ if (c.source && (c.source.doc || c.source.clause)) {
7943
+ out += dumpSourceRefAsRef(c.source, " ", escapeString);
7944
+ }
7728
7945
  out += " }\n";
7729
7946
  }
7730
7947
  out += " }\n";
@@ -7859,6 +8076,12 @@ var parseConstraint = function(id, data) {
7859
8076
  result.onViolation = stripWrapping(t[i++]);
7860
8077
  } else if (keyword === "source") {
7861
8078
  result.source = readSource(unwrapBlock(t[i++]));
8079
+ } else if (keyword === "ref") {
8080
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
8081
+ if (!foldRefIntoLegacy(result, rr.ref)) {
8082
+ (result.refs ??= []).push(rr.ref);
8083
+ }
8084
+ i = rr.next;
7862
8085
  } else {
7863
8086
  i++;
7864
8087
  }
@@ -8057,11 +8280,20 @@ var parseTestPointSet = function(id, data) {
8057
8280
  };
8058
8281
  forEachEntry(
8059
8282
  data,
8060
- (keyword, value) => {
8283
+ (keyword, value, peek) => {
8061
8284
  if (keyword === "description") {
8062
8285
  result.description = unwrapped(value);
8063
8286
  } else if (keyword === "source") {
8064
- result.source = readSource(unwrapBlock(value()));
8287
+ const src = readSource(unwrapBlock(value()));
8288
+ (result.sourceRefs ??= []).push(src);
8289
+ if (!result.source) {
8290
+ result.source = src;
8291
+ }
8292
+ } else if (keyword === "ref") {
8293
+ const r = parseRefFromReaders(value, peek, stripWrapping, unwrapBlock);
8294
+ if (!foldRefIntoLegacy(result, r)) {
8295
+ (result.refs ??= []).push(r);
8296
+ }
8065
8297
  } else if (keyword === "cardinality") {
8066
8298
  result.cardinality = parseCardinality(unwrapBlock(value()));
8067
8299
  } else if (keyword === "repetitions_per_point") {
@@ -8085,9 +8317,11 @@ var dumpTestPointSet = function(s) {
8085
8317
  if (s.description) {
8086
8318
  out += ' description "' + escapeString(s.description) + '"\n';
8087
8319
  }
8088
- if (s.source && (s.source.doc || s.source.clause)) {
8089
- out += ' source { doc "' + escapeString(s.source.doc) + '" clause "' + escapeString(s.source.clause) + '"' + (s.source.fragment ? ' fragment "' + escapeString(s.source.fragment) + '"' : "") + " }\n";
8320
+ const tpsSources = s.sourceRefs && s.sourceRefs.length > 0 ? s.sourceRefs : s.source && (s.source.doc || s.source.clause) ? [s.source] : [];
8321
+ for (const src of tpsSources) {
8322
+ out += dumpSourceRefAsRef(src, " ", escapeString);
8090
8323
  }
8324
+ out += dumpRefs(s.refs, " ", escapeString);
8091
8325
  const ckeys = Object.keys(s.cardinality);
8092
8326
  if (ckeys.length > 0) {
8093
8327
  out += " cardinality {\n";
@@ -8155,7 +8389,7 @@ function readAccepts(block) {
8155
8389
  } else if (cmd === "source_discrepancy") {
8156
8390
  accepts.sourceDiscrepancy = parseSourceDiscrepancy(unwrapBlock(t[i++]));
8157
8391
  } else {
8158
- unwrapBlock(t[i++]);
8392
+ i = skipUnknownValue(t, i, cmd);
8159
8393
  }
8160
8394
  }
8161
8395
  return accepts;
@@ -8195,7 +8429,7 @@ function readLimit(block) {
8195
8429
  } else if (cmd === "source_discrepancy") {
8196
8430
  limit.sourceDiscrepancy = parseSourceDiscrepancy(unwrapBlock(t[i++]));
8197
8431
  } else {
8198
- unwrapBlock(t[i++]);
8432
+ i = skipUnknownValue(t, i, cmd);
8199
8433
  }
8200
8434
  }
8201
8435
  return limit;
@@ -8389,10 +8623,12 @@ var parseRequirement = function(id, data) {
8389
8623
  (result.sourceRefs ??= []).push(src);
8390
8624
  } else if (cmd === "ref") {
8391
8625
  const r = parseRef(t, i, stripWrapping, unwrapBlock);
8392
- (result.refs ??= []).push(r.ref);
8626
+ if (!foldRefIntoLegacy(result, r.ref)) {
8627
+ (result.refs ??= []).push(r.ref);
8628
+ }
8393
8629
  i = r.next;
8394
8630
  } else {
8395
- unwrapBlock(t[i++]);
8631
+ i = skipUnknownValue(t, i, cmd);
8396
8632
  }
8397
8633
  }
8398
8634
  return (ctx) => {
@@ -8530,7 +8766,7 @@ var dumpRequirement = function(r) {
8530
8766
  out += dumpSourceDiscrepancy(r.sourceDiscrepancy, " ") + "\n";
8531
8767
  }
8532
8768
  for (const src of r.sourceRefs ?? (r.source && (r.source.doc || r.source.clause) ? [r.source] : [])) {
8533
- out += ' source { doc "' + escapeString(src.doc) + '" clause "' + escapeString(src.clause) + '"' + (src.fragment ? ' fragment "' + escapeString(src.fragment) + '"' : "") + " }\n";
8769
+ out += dumpSourceRefAsRef(src, " ", escapeString);
8534
8770
  }
8535
8771
  for (const ref of r.refs ?? []) {
8536
8772
  out += " ref " + ref.predicate + ' "' + escapeString(ref.target) + '"' + (ref.note ? ' { note "' + escapeString(ref.note) + '" }' : "") + "\n";
@@ -8571,7 +8807,7 @@ var parseRequirementClass = function(id, data) {
8571
8807
  } else if (cmd === "reference") {
8572
8808
  result.referenceIds = readIdList2(t[i++]);
8573
8809
  } else {
8574
- unwrapBlock(t[i++]);
8810
+ i = skipUnknownValue(t, i, cmd);
8575
8811
  }
8576
8812
  }
8577
8813
  return (ctx) => {
@@ -8714,7 +8950,9 @@ var parsePackage = function(data) {
8714
8950
  manifest.mapsTo = readList(t[i++]);
8715
8951
  } else if (cmd === "ref") {
8716
8952
  const r = parseRef(t, i, stripWrapping, unwrapBlock);
8717
- (manifest.refs ??= []).push(r.ref);
8953
+ if (!foldRefIntoLegacy(manifest, r.ref)) {
8954
+ (manifest.refs ??= []).push(r.ref);
8955
+ }
8718
8956
  i = r.next;
8719
8957
  } else if (cmd === "scheme_type" || cmd === "schemeType") {
8720
8958
  manifest.schemeType = stripWrapping(t[i++]);
@@ -8781,7 +9019,7 @@ var parsePackage = function(data) {
8781
9019
  }
8782
9020
  manifest.source = src;
8783
9021
  } else {
8784
- unwrapBlock(t[i++]);
9022
+ i = skipUnknownValue(t, i, cmd);
8785
9023
  }
8786
9024
  }
8787
9025
  return (ctx) => {
@@ -8832,7 +9070,7 @@ var parseConformanceClass = function(id, data) {
8832
9070
  } else if (cmd === "reference") {
8833
9071
  result.referenceIds = tokenize(stripWrapping(t[i++])).map(stripWrapping);
8834
9072
  } else {
8835
- unwrapBlock(t[i++]);
9073
+ i = skipUnknownValue(t, i, cmd);
8836
9074
  }
8837
9075
  }
8838
9076
  return (ctx) => {
@@ -9258,7 +9496,7 @@ function dumpComposedOf(decl, indent) {
9258
9496
  }
9259
9497
 
9260
9498
  // src/ser-des/config/subject.ts
9261
- function dumpSource2(keyword, src, indent) {
9499
+ function dumpSource(keyword, src, indent) {
9262
9500
  if (!src || !src.doc && !src.clause) {
9263
9501
  return "";
9264
9502
  }
@@ -9294,7 +9532,11 @@ var parseInstrument = function(id, data) {
9294
9532
  referenceIds: [],
9295
9533
  measurand: null,
9296
9534
  components: [],
9297
- structure: []
9535
+ structure: [],
9536
+ // Initialized so the ref fold (docs/primmel/18 §18.4) mirrors the
9537
+ // first derives-from block here — the fold only mirrors slots the
9538
+ // object already carries.
9539
+ source: null
9298
9540
  };
9299
9541
  const t = tokenizePackage(data);
9300
9542
  let i = 0;
@@ -9322,7 +9564,11 @@ var parseInstrument = function(id, data) {
9322
9564
  } else if (cmd === "note") {
9323
9565
  result.note = stripWrapping(t[i++]);
9324
9566
  } else if (cmd === "source") {
9325
- result.source = readSource(unwrapBlock(t[i++]));
9567
+ const src = readSource(unwrapBlock(t[i++]));
9568
+ (result.sourceRefs ??= []).push(src);
9569
+ if (!result.source) {
9570
+ result.source = src;
9571
+ }
9326
9572
  } else if (cmd === "variant") {
9327
9573
  const variantId = stripWrapping(t[i++]);
9328
9574
  const vblock = i < t.length ? unwrapBlock(t[i++]) : "";
@@ -9372,6 +9618,15 @@ var parseInstrument = function(id, data) {
9372
9618
  result.familyNote = stripWrapping(ft[j++]);
9373
9619
  } else if (fc === "source") {
9374
9620
  result.familySource = readSource(unwrapBlock(ft[j++]));
9621
+ } else if (fc === "ref") {
9622
+ const rr = parseRef(ft, j, stripWrapping, unwrapBlock);
9623
+ j = rr.next;
9624
+ if (rr.ref.predicate === "derives-from") {
9625
+ const b = refTargetToSourceRef(rr.ref.target);
9626
+ if (b && !result.familySource) {
9627
+ result.familySource = b;
9628
+ }
9629
+ }
9375
9630
  } else {
9376
9631
  unwrapBlock(ft[j++]);
9377
9632
  }
@@ -9397,8 +9652,14 @@ var parseInstrument = function(id, data) {
9397
9652
  result.modelGroup = parseModelGroup(unwrapBlock(t[i++]));
9398
9653
  } else if (cmd === "reference") {
9399
9654
  result.referenceIds = readReference(t[i++]);
9655
+ } else if (cmd === "ref") {
9656
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
9657
+ if (!foldRefIntoLegacy(result, rr.ref)) {
9658
+ (result.refs ??= []).push(rr.ref);
9659
+ }
9660
+ i = rr.next;
9400
9661
  } else {
9401
- unwrapBlock(t[i++]);
9662
+ i = skipUnknownValue(t, i, cmd);
9402
9663
  }
9403
9664
  }
9404
9665
  return (ctx) => {
@@ -9445,7 +9706,7 @@ function parseMeasurand(block) {
9445
9706
  } else if (cmd === "source") {
9446
9707
  m.source = readSource(unwrapBlock(t[i++]));
9447
9708
  } else {
9448
- unwrapBlock(t[i++]);
9709
+ i = skipUnknownValue(t, i, cmd);
9449
9710
  }
9450
9711
  }
9451
9712
  return m;
@@ -9471,7 +9732,7 @@ function parseComponent2(id, block) {
9471
9732
  } else if (cmd === "source") {
9472
9733
  c.source = readSource(unwrapBlock(t[i++]));
9473
9734
  } else {
9474
- unwrapBlock(t[i++]);
9735
+ i = skipUnknownValue(t, i, cmd);
9475
9736
  }
9476
9737
  }
9477
9738
  return c;
@@ -9515,7 +9776,7 @@ function parseStructure(id, block) {
9515
9776
  } else if (cmd === "source") {
9516
9777
  s.source = readSource(unwrapBlock(t[i++]));
9517
9778
  } else {
9518
- unwrapBlock(t[i++]);
9779
+ i = skipUnknownValue(t, i, cmd);
9519
9780
  }
9520
9781
  }
9521
9782
  return s;
@@ -9559,7 +9820,7 @@ function parseDimension(id, block) {
9559
9820
  } else if (cmd === "values") {
9560
9821
  dim.values = parseDimensionValues(unwrapBlock(t[i++]));
9561
9822
  } else {
9562
- unwrapBlock(t[i++]);
9823
+ i = skipUnknownValue(t, i, cmd);
9563
9824
  }
9564
9825
  }
9565
9826
  return dim;
@@ -9666,10 +9927,19 @@ function parseModelGroup(block) {
9666
9927
  mg.note = stripWrapping(t[i++]);
9667
9928
  } else if (cmd === "source") {
9668
9929
  mg.sources.push(readSource(unwrapBlock(t[i++])));
9930
+ } else if (cmd === "ref") {
9931
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
9932
+ i = rr.next;
9933
+ if (rr.ref.predicate === "derives-from") {
9934
+ const b = refTargetToSourceRef(rr.ref.target);
9935
+ if (b) {
9936
+ mg.sources.push(b);
9937
+ }
9938
+ }
9669
9939
  } else if (cmd === "sample_selection") {
9670
9940
  mg.sampleSelection.push(readSource(unwrapBlock(t[i++])));
9671
9941
  } else {
9672
- unwrapBlock(t[i++]);
9942
+ i = skipUnknownValue(t, i, cmd);
9673
9943
  }
9674
9944
  }
9675
9945
  return mg;
@@ -9704,7 +9974,7 @@ var dumpInstrument = function(inst) {
9704
9974
  }
9705
9975
  out += " }\n";
9706
9976
  }
9707
- out += dumpSource2("source", m.source, " ");
9977
+ out += dumpSource("source", m.source, " ");
9708
9978
  out += " }\n";
9709
9979
  }
9710
9980
  for (const c of inst.components ?? []) {
@@ -9744,7 +10014,7 @@ var dumpInstrument = function(inst) {
9744
10014
  if (s.note) {
9745
10015
  out += ' note "' + escapeString(s.note) + '"\n';
9746
10016
  }
9747
- out += dumpSource2("source", s.source, " ");
10017
+ out += dumpSource("source", s.source, " ");
9748
10018
  out += " }\n";
9749
10019
  }
9750
10020
  if (inst.definition) {
@@ -9784,7 +10054,7 @@ var dumpInstrument = function(inst) {
9784
10054
  if (d.description) {
9785
10055
  out += ' description "' + escapeString(d.description) + '"\n';
9786
10056
  }
9787
- out += dumpSource2("reference", d.source, " ");
10057
+ out += dumpSource("reference", d.source, " ");
9788
10058
  if (d.values.length > 0) {
9789
10059
  out += " values {\n";
9790
10060
  for (const v of d.values) {
@@ -9838,7 +10108,9 @@ var dumpInstrument = function(inst) {
9838
10108
  if (inst.familyNote) {
9839
10109
  out += ' note "' + escapeString(inst.familyNote) + '"\n';
9840
10110
  }
9841
- out += dumpSource2("source", inst.familySource ?? null, " ");
10111
+ if (inst.familySource && (inst.familySource.doc || inst.familySource.clause)) {
10112
+ out += dumpSourceRefAsRef(inst.familySource, " ", escapeString);
10113
+ }
9842
10114
  out += " }\n";
9843
10115
  }
9844
10116
  if (inst.familyCriteria.length > 0) {
@@ -9876,14 +10148,18 @@ var dumpInstrument = function(inst) {
9876
10148
  " "
9877
10149
  );
9878
10150
  for (const s of inst.modelGroup.sources ?? []) {
9879
- out += dumpSource2("source", s, " ");
10151
+ out += dumpSourceRefAsRef(s, " ", escapeString);
9880
10152
  }
9881
10153
  for (const s of inst.modelGroup.sampleSelection ?? []) {
9882
- out += dumpSource2("sample_selection", s, " ");
10154
+ out += dumpSource("sample_selection", s, " ");
9883
10155
  }
9884
10156
  out += " }\n";
9885
10157
  }
9886
- out += dumpSource2("source", inst.source ?? null, " ");
10158
+ const instSources = inst.sourceRefs && inst.sourceRefs.length > 0 ? inst.sourceRefs : inst.source ? [inst.source] : [];
10159
+ for (const s of instSources) {
10160
+ out += dumpSourceRefAsRef(s, " ", escapeString);
10161
+ }
10162
+ out += dumpRefs(inst.refs, " ", escapeString);
9887
10163
  out += dumpIdList("reference", inst.referenceIds, " ");
9888
10164
  out += "}\n";
9889
10165
  return out;
@@ -9921,7 +10197,11 @@ var parseAttributeDefinition = function(id, data) {
9921
10197
  } else if (cmd === "definition") {
9922
10198
  result.definition = stripWrapping(t[i++]);
9923
10199
  } else if (cmd === "source" || cmd === "reference") {
9924
- result.source = readSource(unwrapBlock(t[i++]));
10200
+ const src = readSource(unwrapBlock(t[i++]));
10201
+ (result.sourceRefs ??= []).push(src);
10202
+ if (!result.source) {
10203
+ result.source = src;
10204
+ }
9925
10205
  } else if (cmd === "quantity_kind") {
9926
10206
  result.quantityKind = stripWrapping(t[i++]);
9927
10207
  } else if (cmd === "unit") {
@@ -9946,8 +10226,14 @@ var parseAttributeDefinition = function(id, data) {
9946
10226
  result.irdi = stripWrapping(t[i++]);
9947
10227
  } else if (cmd === "derived") {
9948
10228
  result.derived = stripWrapping(t[i++]);
10229
+ } else if (cmd === "ref") {
10230
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
10231
+ if (!foldRefIntoLegacy(result, rr.ref)) {
10232
+ (result.refs ??= []).push(rr.ref);
10233
+ }
10234
+ i = rr.next;
9949
10235
  } else {
9950
- unwrapBlock(t[i++]);
10236
+ i = skipUnknownValue(t, i, cmd);
9951
10237
  }
9952
10238
  }
9953
10239
  return (ctx) => {
@@ -9966,7 +10252,11 @@ var dumpAttributeDefinition = function(a) {
9966
10252
  if (a.definition) {
9967
10253
  out += ' definition "' + escapeString(a.definition) + '"\n';
9968
10254
  }
9969
- out += dumpSource2("source", a.source, " ");
10255
+ const attrSources = a.sourceRefs && a.sourceRefs.length > 0 ? a.sourceRefs : a.source ? [a.source] : [];
10256
+ for (const s of attrSources) {
10257
+ out += dumpSourceRefAsRef(s, " ", escapeString);
10258
+ }
10259
+ out += dumpRefs(a.refs, " ", escapeString);
9970
10260
  if (a.quantityKind) {
9971
10261
  out += " quantity_kind " + a.quantityKind + "\n";
9972
10262
  }
@@ -10038,8 +10328,14 @@ var parseCapability = function(id, data) {
10038
10328
  result.verifiedByTests = readReference(t[i++]);
10039
10329
  } else if (cmd === "reference") {
10040
10330
  result.referenceIds = readReference(t[i++]);
10331
+ } else if (cmd === "ref") {
10332
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
10333
+ if (!foldRefIntoLegacy(result, rr.ref)) {
10334
+ (result.refs ??= []).push(rr.ref);
10335
+ }
10336
+ i = rr.next;
10041
10337
  } else {
10042
- unwrapBlock(t[i++]);
10338
+ i = skipUnknownValue(t, i, cmd);
10043
10339
  }
10044
10340
  }
10045
10341
  return (ctx) => {
@@ -10064,6 +10360,7 @@ var dumpCapability = function(c) {
10064
10360
  out += dumpIdList("satisfies_requirements", c.satisfiesRequirements, " ");
10065
10361
  out += dumpIdList("verified_by_tests", c.verifiedByTests, " ");
10066
10362
  out += dumpIdList("reference", c.referenceIds, " ");
10363
+ out += dumpRefs(c.refs, " ", escapeString);
10067
10364
  out += "}\n";
10068
10365
  return out;
10069
10366
  };
@@ -10091,11 +10388,21 @@ var parseBehavior = function(id, data) {
10091
10388
  } else if (cmd === "response") {
10092
10389
  result.response = stripWrapping(t[i++]);
10093
10390
  } else if (cmd === "source" || cmd === "reference") {
10094
- result.source = readSource(unwrapBlock(t[i++]));
10391
+ const src = readSource(unwrapBlock(t[i++]));
10392
+ (result.sourceRefs ??= []).push(src);
10393
+ if (!result.source) {
10394
+ result.source = src;
10395
+ }
10095
10396
  } else if (cmd === "verified_by" || cmd === "verified_by_tests") {
10096
10397
  result.verifiedBy = readReference(t[i++]);
10398
+ } else if (cmd === "ref") {
10399
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
10400
+ if (!foldRefIntoLegacy(result, rr.ref)) {
10401
+ (result.refs ??= []).push(rr.ref);
10402
+ }
10403
+ i = rr.next;
10097
10404
  } else {
10098
- unwrapBlock(t[i++]);
10405
+ i = skipUnknownValue(t, i, cmd);
10099
10406
  }
10100
10407
  }
10101
10408
  return (ctx) => {
@@ -10114,7 +10421,11 @@ var dumpBehavior = function(b) {
10114
10421
  if (b.response) {
10115
10422
  out += ' response "' + escapeString(b.response) + '"\n';
10116
10423
  }
10117
- out += dumpSource2("source", b.source, " ");
10424
+ const behaviorSources = b.sourceRefs && b.sourceRefs.length > 0 ? b.sourceRefs : b.source ? [b.source] : [];
10425
+ for (const s of behaviorSources) {
10426
+ out += dumpSourceRefAsRef(s, " ", escapeString);
10427
+ }
10428
+ out += dumpRefs(b.refs, " ", escapeString);
10118
10429
  out += dumpIdList("verified_by", b.verifiedBy, " ");
10119
10430
  out += "}\n";
10120
10431
  return out;
@@ -10149,10 +10460,28 @@ var parseConditionSet = function(id, data) {
10149
10460
  if (!result.source) {
10150
10461
  result.source = src;
10151
10462
  }
10463
+ } else if (cmd === "ref") {
10464
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
10465
+ i = rr.next;
10466
+ if (rr.ref.predicate === "derives-from") {
10467
+ const b = refTargetToSourceRef(rr.ref.target);
10468
+ if (b) {
10469
+ result.sources.push(b);
10470
+ if (!result.source) {
10471
+ result.source = b;
10472
+ }
10473
+ } else {
10474
+ (result.refs ??= []).push(rr.ref);
10475
+ }
10476
+ } else if (rr.ref.predicate === "cites") {
10477
+ result.referenceIds.push(rr.ref.target);
10478
+ } else {
10479
+ (result.refs ??= []).push(rr.ref);
10480
+ }
10152
10481
  } else if (cmd === "reference") {
10153
10482
  result.referenceIds = readReference(t[i++]);
10154
10483
  } else {
10155
- unwrapBlock(t[i++]);
10484
+ i = skipUnknownValue(t, i, cmd);
10156
10485
  }
10157
10486
  }
10158
10487
  return (ctx) => {
@@ -10231,9 +10560,10 @@ var dumpConditionSet = function(cs) {
10231
10560
  }
10232
10561
  const sources = cs.sources && cs.sources.length > 0 ? cs.sources : cs.source ? [cs.source] : [];
10233
10562
  for (const s of sources) {
10234
- out += dumpSource2("source", s, " ");
10563
+ out += dumpSourceRefAsRef(s, " ", escapeString);
10235
10564
  }
10236
10565
  out += dumpIdList("reference", cs.referenceIds, " ");
10566
+ out += dumpRefs(cs.refs, " ", escapeString);
10237
10567
  out += "}\n";
10238
10568
  return out;
10239
10569
  };
@@ -10362,7 +10692,7 @@ function readCharacteristicBlock(block) {
10362
10692
  } else if (cmd === "source" || cmd === "reference") {
10363
10693
  c.source = readSource(unwrapBlock(t[i++]));
10364
10694
  } else {
10365
- unwrapBlock(t[i++]);
10695
+ i = skipUnknownValue(t, i, cmd);
10366
10696
  }
10367
10697
  }
10368
10698
  return c;
@@ -10626,7 +10956,7 @@ var parseSubject = function(id, data) {
10626
10956
  } else if (cmd === "reference") {
10627
10957
  result.referenceIds = readReference(t[i++]);
10628
10958
  } else {
10629
- unwrapBlock(t[i++]);
10959
+ i = skipUnknownValue(t, i, cmd);
10630
10960
  }
10631
10961
  }
10632
10962
  return (ctx) => {
@@ -10778,7 +11108,7 @@ function dumpSubjectPromises(promises) {
10778
11108
  out += ' statement "' + escapeString(p.statement) + '"\n';
10779
11109
  }
10780
11110
  out += dumpIdList("verified_by", p.verifiedBy, " ");
10781
- out += dumpSource2("source", p.source ?? null, " ");
11111
+ out += dumpSource("source", p.source ?? null, " ");
10782
11112
  out += " }\n";
10783
11113
  }
10784
11114
  out += " }\n";
@@ -10810,7 +11140,7 @@ function dumpSubjectCharacteristics(map) {
10810
11140
  if (c.unit) {
10811
11141
  out += ' unit "' + escapeString(c.unit) + '"\n';
10812
11142
  }
10813
- out += dumpSource2("source", c.source ?? null, " ");
11143
+ out += dumpSource("source", c.source ?? null, " ");
10814
11144
  out += " }\n";
10815
11145
  continue;
10816
11146
  }
@@ -11082,14 +11412,6 @@ var instanceConstruct = {
11082
11412
  };
11083
11413
 
11084
11414
  // src/ser-des/config/artifact.ts
11085
- function dumpSource3(keyword, src, indent) {
11086
- if (!src || !src.doc && !src.clause) {
11087
- return "";
11088
- }
11089
- const frag = src.fragment ? ` fragment "${escapeString(src.fragment)}"` : "";
11090
- return `${indent}${keyword} { doc "${escapeString(src.doc)}" clause "${escapeString(src.clause)}"${frag} }
11091
- `;
11092
- }
11093
11415
  function readIdList4(block) {
11094
11416
  return tokenize(stripWrapping(block)).map(stripColon).map(stripWrapping).filter((s) => s.length > 0);
11095
11417
  }
@@ -11183,7 +11505,7 @@ function parseContentContract(block) {
11183
11505
  } else if (cmd === "media") {
11184
11506
  contract.media = readContractMedia(unwrapBlock(t[i++]));
11185
11507
  } else {
11186
- unwrapBlock(t[i++]);
11508
+ i = skipUnknownValue(t, i, cmd);
11187
11509
  }
11188
11510
  }
11189
11511
  return contract;
@@ -11224,11 +11546,21 @@ var parseArtifactDefinition = function(id, data) {
11224
11546
  } else if (cmd === "retention") {
11225
11547
  result.retention = stripWrapping(t[i++]);
11226
11548
  } else if (cmd === "source") {
11227
- result.source = readSource(unwrapBlock(t[i++]));
11549
+ const src = readSource(unwrapBlock(t[i++]));
11550
+ (result.sourceRefs ??= []).push(src);
11551
+ if (!result.source) {
11552
+ result.source = src;
11553
+ }
11228
11554
  } else if (cmd === "reference") {
11229
11555
  result.referenceIds = readReference3(t[i++]);
11556
+ } else if (cmd === "ref") {
11557
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
11558
+ if (!foldRefIntoLegacy(result, rr.ref)) {
11559
+ (result.refs ??= []).push(rr.ref);
11560
+ }
11561
+ i = rr.next;
11230
11562
  } else {
11231
- unwrapBlock(t[i++]);
11563
+ i = skipUnknownValue(t, i, cmd);
11232
11564
  }
11233
11565
  }
11234
11566
  return (ctx) => {
@@ -11289,7 +11621,11 @@ var dumpArtifactDefinition = function(d) {
11289
11621
  if (d.retention) {
11290
11622
  out += ' retention "' + escapeString(d.retention) + '"\n';
11291
11623
  }
11292
- out += dumpSource3("source", d.source, " ");
11624
+ const artifactSources = d.sourceRefs && d.sourceRefs.length > 0 ? d.sourceRefs : d.source ? [d.source] : [];
11625
+ for (const s of artifactSources) {
11626
+ out += dumpSourceRefAsRef(s, " ", escapeString);
11627
+ }
11628
+ out += dumpRefs(d.refs, " ", escapeString);
11293
11629
  out += dumpIdList2("reference", d.referenceIds, " ");
11294
11630
  out += "}\n";
11295
11631
  return out;
@@ -11324,7 +11660,7 @@ var parseArtifactInstance = function(id, data) {
11324
11660
  } else if (cmd === "reference") {
11325
11661
  result.referenceIds = readReference3(t[i++]);
11326
11662
  } else {
11327
- unwrapBlock(t[i++]);
11663
+ i = skipUnknownValue(t, i, cmd);
11328
11664
  }
11329
11665
  }
11330
11666
  return (ctx) => {
@@ -11875,6 +12211,12 @@ var parseTestSequence = function(id, data) {
11875
12211
  sequence.description = stripWrapping(t[i++]);
11876
12212
  } else if (command === "sample_applicability") {
11877
12213
  sequence.sampleApplicability = stripWrapping(t[i++]);
12214
+ } else if (command === "ref") {
12215
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
12216
+ if (!foldRefIntoLegacy(sequence, rr.ref)) {
12217
+ sequence.refs = [...sequence.refs ?? [], rr.ref];
12218
+ }
12219
+ i = rr.next;
11878
12220
  } else if (command === "source") {
11879
12221
  sequence.sourceRefs.push(readSource(unwrapBlock(t[i++])));
11880
12222
  } else if (command === "step") {
@@ -11930,8 +12272,11 @@ var dumpTestSequence = function(seq) {
11930
12272
  if (seq.sampleApplicability !== "") {
11931
12273
  out += " sample_applicability " + dumpBareSafe(seq.sampleApplicability) + "\n";
11932
12274
  }
12275
+ for (const r of seq.refs ?? []) {
12276
+ out += " ref " + r.predicate + ' "' + escapeString(r.target) + '"' + (r.note ? ' { note "' + escapeString(r.note) + '" }' : "") + "\n";
12277
+ }
11933
12278
  for (const src of seq.sourceRefs) {
11934
- out += ' source { doc "' + escapeString(src.doc) + '" clause "' + escapeString(src.clause) + '"' + (src.fragment ? ' fragment "' + escapeString(src.fragment) + '"' : "") + " }\n";
12279
+ out += dumpSourceRefAsRef(src, " ", escapeString);
11935
12280
  }
11936
12281
  out += "}\n";
11937
12282
  return out;
@@ -11955,13 +12300,18 @@ var parseFormulasUsed = function(id, data) {
11955
12300
  };
11956
12301
  forEachEntry(
11957
12302
  data,
11958
- (command, value) => {
12303
+ (command, value, peek) => {
11959
12304
  if (command === "name") {
11960
12305
  trace.name = stripWrapping(value());
11961
12306
  } else if (command === "description") {
11962
12307
  trace.description = stripWrapping(value());
11963
12308
  } else if (command === "formulas") {
11964
12309
  trace.formulas.push(...readEntryTokens(value()));
12310
+ } else if (command === "ref") {
12311
+ const r = parseRefFromReaders(value, peek, stripWrapping, unwrapBlock);
12312
+ if (!foldRefIntoLegacy(trace, r)) {
12313
+ (trace.refs ??= []).push(r);
12314
+ }
11965
12315
  } else if (command === "source") {
11966
12316
  trace.sourceRefs.push(readSource(unwrapBlock(value())));
11967
12317
  } else {
@@ -11987,8 +12337,11 @@ var dumpFormulasUsed = function(fu) {
11987
12337
  if (fu.formulas.length > 0) {
11988
12338
  out += " formulas { " + fu.formulas.map(dumpBareSafe).join(" ") + " }\n";
11989
12339
  }
12340
+ for (const r of fu.refs ?? []) {
12341
+ out += " ref " + r.predicate + ' "' + escapeString(r.target) + '"' + (r.note ? ' { note "' + escapeString(r.note) + '" }' : "") + "\n";
12342
+ }
11990
12343
  for (const src of fu.sourceRefs) {
11991
- out += ' source { doc "' + escapeString(src.doc) + '" clause "' + escapeString(src.clause) + '"' + (src.fragment ? ' fragment "' + escapeString(src.fragment) + '"' : "") + " }\n";
12344
+ out += dumpSourceRefAsRef(src, " ", escapeString);
11992
12345
  }
11993
12346
  out += "}\n";
11994
12347
  return out;
@@ -15450,6 +15803,19 @@ var CHECK_RULES = [
15450
15803
  "error",
15451
15804
  "normal",
15452
15805
  "TODO.integration/14, the composed_of construct (TODO.v3/03 Phase 2)"
15806
+ ),
15807
+ // ── the relation registry (docs/primmel/18 §18.6) ──────────────────
15808
+ // C103: every ref predicate resolves against the composed registry —
15809
+ // a typo is an error, not a silent new predicate. The rule only fires
15810
+ // when the package set declares a registry: the predicate vocabulary
15811
+ // is data (the metamodel layer's predicates.prl), never grammar.
15812
+ R(
15813
+ "C103",
15814
+ "declared-predicate",
15815
+ "base",
15816
+ "error",
15817
+ "normal",
15818
+ "docs/primmel/18 \xA718.6 (the unified reference/relation construct)"
15453
15819
  )
15454
15820
  ];
15455
15821
  var byId = new Map(CHECK_RULES.map((r) => [r.id, r]));
@@ -16386,6 +16752,7 @@ function checkPackage(dir, options = {}) {
16386
16752
  }
16387
16753
  issues.push(...checkEditionLifecycle(dir, standard));
16388
16754
  issues.push(...checkSpellingCodes(standard));
16755
+ issues.push(...checkDeclaredPredicates(standard));
16389
16756
  const reqIds = new Set(
16390
16757
  (standard.requirements ?? []).map((r) => r.id)
16391
16758
  );
@@ -19845,6 +20212,81 @@ function checkSpellingCodes(standard) {
19845
20212
  }
19846
20213
  return issues;
19847
20214
  }
20215
+ function checkDeclaredPredicates(standard) {
20216
+ const issues = [];
20217
+ const registry = new Set((standard.predicates ?? []).map((p) => p.id));
20218
+ if (registry.size === 0) {
20219
+ return issues;
20220
+ }
20221
+ const visit = (owner, refs) => {
20222
+ for (const r of refs ?? []) {
20223
+ if (!registry.has(r.predicate)) {
20224
+ issues.push({
20225
+ check: "C103",
20226
+ severity: "error",
20227
+ message: `${owner}: ref predicate "${r.predicate}" is not declared in the composed predicate registry (declared-predicate)`
20228
+ });
20229
+ }
20230
+ }
20231
+ };
20232
+ const visitFields = (owner, fields) => {
20233
+ for (const f of fields) {
20234
+ const here = `${owner} field ${f.name}`;
20235
+ visit(here, f.refs);
20236
+ if (f.fields && f.fields.length > 0) {
20237
+ visitFields(here, f.fields);
20238
+ }
20239
+ }
20240
+ };
20241
+ const m = standard.packageManifest;
20242
+ if (m) {
20243
+ visit(`package "${m.id}"`, m.refs);
20244
+ }
20245
+ for (const r of standard.requirements ?? []) {
20246
+ visit(`requirement ${r.id}`, r.refs);
20247
+ }
20248
+ for (const t of standard.conformanceTests ?? []) {
20249
+ visit(`conformance_test ${t.id}`, t.refs);
20250
+ }
20251
+ for (const f of standard.forms ?? []) {
20252
+ visit(`form ${f.id}`, f.refs);
20253
+ visitFields(`form ${f.id}`, f.fields ?? []);
20254
+ }
20255
+ for (const s of standard.subforms ?? []) {
20256
+ visitFields(`subform ${s.id}`, s.fields ?? []);
20257
+ }
20258
+ for (const c of standard.calculations ?? []) {
20259
+ visit(`calculation ${c.id}`, c.refs);
20260
+ }
20261
+ for (const s of standard.symbols ?? []) {
20262
+ visit(`symbol ${s.id}`, s.refs);
20263
+ }
20264
+ for (const t of standard.terms ?? []) {
20265
+ visit(`term ${t.id}`, t.refs);
20266
+ }
20267
+ for (const t of standard.tables ?? []) {
20268
+ visit(`table ${t.id}`, t.refs);
20269
+ }
20270
+ for (const c of standard.constraints ?? []) {
20271
+ visit(`constraint ${c.id}`, c.refs);
20272
+ }
20273
+ for (const k of standard.competenceKinds ?? []) {
20274
+ visit(`competence_kind ${k.id}`, k.refs);
20275
+ }
20276
+ for (const f of standard.formulasUsed ?? []) {
20277
+ visit(`formulas_used ${f.id}`, f.refs);
20278
+ }
20279
+ for (const s of standard.testSequences ?? []) {
20280
+ visit(`test_sequence ${s.id}`, s.refs);
20281
+ }
20282
+ for (const c of standard.conditionSets ?? []) {
20283
+ visit(`condition_set ${c.id}`, c.refs);
20284
+ }
20285
+ for (const i of standard.instruments ?? []) {
20286
+ visit(`instrument ${i.id}`, i.refs);
20287
+ }
20288
+ return issues;
20289
+ }
19848
20290
  function checkEditionLifecycle(dir, standard) {
19849
20291
  const issues = [];
19850
20292
  const err = (check, message) => issues.push({ check, severity: "error", message });