@primmel/primmel 1.12.0 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/src/check-rules.d.ts.map +1 -1
  2. package/dist/src/check-rules.js +42 -0
  3. package/dist/src/check-rules.js.map +1 -1
  4. package/dist/src/check.d.ts.map +1 -1
  5. package/dist/src/check.js +203 -0
  6. package/dist/src/check.js.map +1 -1
  7. package/dist/src/model-diff.d.ts.map +1 -1
  8. package/dist/src/model-diff.js +5 -0
  9. package/dist/src/model-diff.js.map +1 -1
  10. package/dist/src/ser-des/config/calculation.d.ts.map +1 -1
  11. package/dist/src/ser-des/config/calculation.js +134 -18
  12. package/dist/src/ser-des/config/calculation.js.map +1 -1
  13. package/dist/src/ser-des/config/commonTestCondition.d.ts +5 -0
  14. package/dist/src/ser-des/config/commonTestCondition.d.ts.map +1 -0
  15. package/dist/src/ser-des/config/commonTestCondition.js +75 -0
  16. package/dist/src/ser-des/config/commonTestCondition.js.map +1 -0
  17. package/dist/src/ser-des/config/formulaNote.d.ts +5 -0
  18. package/dist/src/ser-des/config/formulaNote.d.ts.map +1 -0
  19. package/dist/src/ser-des/config/formulaNote.js +66 -0
  20. package/dist/src/ser-des/config/formulaNote.js.map +1 -0
  21. package/dist/src/ser-des/config/index.d.ts.map +1 -1
  22. package/dist/src/ser-des/config/index.js +52 -0
  23. package/dist/src/ser-des/config/index.js.map +1 -1
  24. package/dist/src/ser-des/config/partAnnex.d.ts +5 -0
  25. package/dist/src/ser-des/config/partAnnex.d.ts.map +1 -0
  26. package/dist/src/ser-des/config/partAnnex.js +91 -0
  27. package/dist/src/ser-des/config/partAnnex.js.map +1 -0
  28. package/dist/src/ser-des/config/storyline.d.ts +7 -0
  29. package/dist/src/ser-des/config/storyline.d.ts.map +1 -0
  30. package/dist/src/ser-des/config/storyline.js +264 -0
  31. package/dist/src/ser-des/config/storyline.js.map +1 -0
  32. package/dist/src/ser-des/config/subject.d.ts.map +1 -1
  33. package/dist/src/ser-des/config/subject.js +93 -0
  34. package/dist/src/ser-des/config/subject.js.map +1 -1
  35. package/dist/src/ser-des/package.d.ts.map +1 -1
  36. package/dist/src/ser-des/package.js +5 -0
  37. package/dist/src/ser-des/package.js.map +1 -1
  38. package/dist/src/ser-des/parse.d.ts.map +1 -1
  39. package/dist/src/ser-des/parse.js +5 -0
  40. package/dist/src/ser-des/parse.js.map +1 -1
  41. package/dist/src/ser-des/types.d.ts +10 -0
  42. package/dist/src/ser-des/types.d.ts.map +1 -1
  43. package/dist/src/types/Calculation.d.ts +35 -0
  44. package/dist/src/types/Calculation.d.ts.map +1 -1
  45. package/dist/src/types/CommonTestCondition.d.ts +15 -0
  46. package/dist/src/types/CommonTestCondition.d.ts.map +1 -0
  47. package/dist/src/types/CommonTestCondition.js +22 -0
  48. package/dist/src/types/CommonTestCondition.js.map +1 -0
  49. package/dist/src/types/PartAnnex.d.ts +18 -0
  50. package/dist/src/types/PartAnnex.d.ts.map +1 -0
  51. package/dist/src/types/PartAnnex.js +29 -0
  52. package/dist/src/types/PartAnnex.js.map +1 -0
  53. package/dist/src/types/Standard.d.ts +20 -0
  54. package/dist/src/types/Standard.d.ts.map +1 -1
  55. package/dist/src/types/Storyline.d.ts +62 -0
  56. package/dist/src/types/Storyline.d.ts.map +1 -0
  57. package/dist/src/types/Storyline.js +51 -0
  58. package/dist/src/types/Storyline.js.map +1 -0
  59. package/dist/src/types/Subject.d.ts +33 -0
  60. package/dist/src/types/Subject.d.ts.map +1 -1
  61. package/dist/src/types/Symbol.d.ts +17 -0
  62. package/dist/src/types/Symbol.d.ts.map +1 -1
  63. package/dist-browser/index.mjs +1110 -771
  64. package/dist-cli/primmel.mjs +924 -41
  65. package/package.json +1 -1
@@ -220,10 +220,12 @@ function parse(mmelString, parsers, options = {}) {
220
220
  forms: {},
221
221
  subforms: {},
222
222
  symbols: {},
223
+ formulaNotes: {},
223
224
  calculations: {},
224
225
  verdicts: {},
225
226
  referenceMaterials: {},
226
227
  testPointSets: {},
228
+ commonTestConditions: {},
227
229
  competenceKinds: {},
228
230
  // The ISO/IEC 17067 scheme-type register (smart TODO.roadmap/40 batch 2)
229
231
  schemeActivityKinds: {},
@@ -269,6 +271,9 @@ function parse(mmelString, parsers, options = {}) {
269
271
  // The document modules + informative annexes (smart TODO.roadmap/40 batch 2)
270
272
  documentModules: {},
271
273
  informativeAnnexes: {},
274
+ partAnnexes: {},
275
+ demoWorlds: {},
276
+ storylines: {},
272
277
  // Primmel v3 twin interface (TODO.roadmap/32)
273
278
  connectorProfiles: {},
274
279
  // Primmel v3 continuous compliance (TODO.roadmap/34)
@@ -5663,6 +5668,47 @@ var dumpSymbol = function(s) {
5663
5668
  return out;
5664
5669
  };
5665
5670
 
5671
+ // src/ser-des/config/formulaNote.ts
5672
+ function readIdList(block) {
5673
+ return tokenize(stripWrapping(block)).map(stripColon).map(stripWrapping).filter((s) => s.length > 0);
5674
+ }
5675
+ var parseFormulaNote = (id, data) => {
5676
+ const note = {
5677
+ id,
5678
+ text: "",
5679
+ appliesTo: []
5680
+ };
5681
+ forEachEntry(
5682
+ data,
5683
+ (keyword, value) => {
5684
+ if (keyword === "text") {
5685
+ note.text = stripWrapping(value());
5686
+ } else if (keyword === "applies_to") {
5687
+ note.appliesTo = readIdList(value());
5688
+ } else {
5689
+ return false;
5690
+ }
5691
+ return true;
5692
+ },
5693
+ { construct: "formula_note", id }
5694
+ );
5695
+ return (ctx) => {
5696
+ ctx.formulaNotes[id] = note;
5697
+ return ctx;
5698
+ };
5699
+ };
5700
+ var dumpFormulaNote = function(n) {
5701
+ let out = "formula_note " + n.id + " {\n";
5702
+ if (n.text) {
5703
+ out += ' text "' + escapeString(n.text) + '"\n';
5704
+ }
5705
+ if (n.appliesTo.length > 0) {
5706
+ out += " applies_to { " + n.appliesTo.map(dumpBareSafe).join(" ") + " }\n";
5707
+ }
5708
+ out += "}\n";
5709
+ return out;
5710
+ };
5711
+
5666
5712
  // src/ser-des/config/calculation.ts
5667
5713
  var parseCalculation = function(id, data) {
5668
5714
  const result = {
@@ -5755,6 +5801,16 @@ var parseCalculation = function(id, data) {
5755
5801
  result.lookup = parseLookup(unwrapBlock(t[i++]));
5756
5802
  } else if (command === "profile") {
5757
5803
  result.profile = stripWrapping(t[i++]);
5804
+ } else if (command === "variant") {
5805
+ const vid = stripWrapping(t[i++]);
5806
+ if (i >= t.length || !t[i].startsWith("{")) {
5807
+ throw new Error(
5808
+ `Parsing error: calculation. ID ${id}: variant ${vid} is missing its block`
5809
+ );
5810
+ }
5811
+ (result.variants ??= []).push(
5812
+ parseVariant(vid, unwrapBlock(t[i++]), id)
5813
+ );
5758
5814
  } else {
5759
5815
  i++;
5760
5816
  }
@@ -5970,6 +6026,102 @@ function parseLookup(block) {
5970
6026
  }
5971
6027
  return lookup;
5972
6028
  }
6029
+ var VARIANT_TYPES = [
6030
+ "expression",
6031
+ "table_lookup",
6032
+ "profile_lookup",
6033
+ "pass_fail"
6034
+ ];
6035
+ function parseVariant(vid, block, calcId) {
6036
+ const variant = {
6037
+ id: vid,
6038
+ type: "",
6039
+ label: "",
6040
+ description: "",
6041
+ params: [],
6042
+ expression: "",
6043
+ lookup: null,
6044
+ profile: ""
6045
+ };
6046
+ const t = tokenizePackage(block);
6047
+ let i = 0;
6048
+ while (i < t.length) {
6049
+ const cmd = t[i++];
6050
+ if (i >= t.length) {
6051
+ break;
6052
+ }
6053
+ if (cmd === "type") {
6054
+ const type = stripWrapping(t[i++]);
6055
+ if (!VARIANT_TYPES.includes(type)) {
6056
+ throw new Error(
6057
+ `Parsing error: calculation. ID ${calcId}: variant ${vid}: Unknown variant type "${type}" (valid: ${VARIANT_TYPES.join(", ")})`
6058
+ );
6059
+ }
6060
+ variant.type = type;
6061
+ } else if (cmd === "label") {
6062
+ variant.label = stripWrapping(t[i++]);
6063
+ } else if (cmd === "description") {
6064
+ variant.description = stripWrapping(t[i++]);
6065
+ } else if (cmd === "params") {
6066
+ variant.params = tokenize(stripWrapping(t[i++])).map(stripWrapping).filter((s) => s.length > 0);
6067
+ } else if (cmd === "expression") {
6068
+ variant.expression = stripWrapping(t[i++]);
6069
+ } else if (cmd === "lookup") {
6070
+ variant.lookup = parseLookup(unwrapBlock(t[i++]));
6071
+ } else if (cmd === "profile") {
6072
+ variant.profile = stripWrapping(t[i++]);
6073
+ } else {
6074
+ unwrapBlock(t[i++]);
6075
+ }
6076
+ }
6077
+ return variant;
6078
+ }
6079
+ function dumpLookupFields(l) {
6080
+ let out = "";
6081
+ if (l.key) {
6082
+ out += "key " + l.key + " ";
6083
+ }
6084
+ if (l.variable) {
6085
+ out += "variable " + l.variable + " ";
6086
+ }
6087
+ if (l.multiplier) {
6088
+ out += "multiplier " + l.multiplier + " ";
6089
+ }
6090
+ if (l.defaultTier) {
6091
+ out += "default_tier { factor " + l.defaultTier.factor;
6092
+ if (l.defaultTier.mode) {
6093
+ out += " mode " + l.defaultTier.mode;
6094
+ }
6095
+ out += " } ";
6096
+ }
6097
+ return out;
6098
+ }
6099
+ function dumpVariant(v) {
6100
+ let out = " variant " + dumpBareSafe(v.id) + " {\n";
6101
+ if (v.type) {
6102
+ out += " type " + v.type + "\n";
6103
+ }
6104
+ if (v.label) {
6105
+ out += ' label "' + escapeString(v.label) + '"\n';
6106
+ }
6107
+ if (v.description) {
6108
+ out += ' description "' + escapeString(v.description) + '"\n';
6109
+ }
6110
+ if (v.params.length > 0) {
6111
+ out += " params { " + v.params.map(dumpBareSafe).join(" ") + " }\n";
6112
+ }
6113
+ if (v.expression) {
6114
+ out += ' expression "' + escapeString(v.expression) + '"\n';
6115
+ }
6116
+ if (v.lookup) {
6117
+ out += " lookup { " + dumpLookupFields(v.lookup) + "}\n";
6118
+ }
6119
+ if (v.profile) {
6120
+ out += " profile " + dumpBareSafe(v.profile) + "\n";
6121
+ }
6122
+ out += " }\n";
6123
+ return out;
6124
+ }
5973
6125
  var resolveCalculation = function(ctx, unresolved) {
5974
6126
  const ref = [];
5975
6127
  for (const id of unresolved._relations.ref) {
@@ -6058,28 +6210,14 @@ var dumpCalculation = function(c) {
6058
6210
  out += " params { " + c.params.join(" ") + " }\n";
6059
6211
  }
6060
6212
  if (c.lookup) {
6061
- out += " lookup { ";
6062
- if (c.lookup.key) {
6063
- out += "key " + c.lookup.key + " ";
6064
- }
6065
- if (c.lookup.variable) {
6066
- out += "variable " + c.lookup.variable + " ";
6067
- }
6068
- if (c.lookup.multiplier) {
6069
- out += "multiplier " + c.lookup.multiplier + " ";
6070
- }
6071
- if (c.lookup.defaultTier) {
6072
- out += "default_tier { factor " + c.lookup.defaultTier.factor;
6073
- if (c.lookup.defaultTier.mode) {
6074
- out += " mode " + c.lookup.defaultTier.mode;
6075
- }
6076
- out += " } ";
6077
- }
6078
- out += "}\n";
6213
+ out += " lookup { " + dumpLookupFields(c.lookup) + "}\n";
6079
6214
  }
6080
6215
  if (c.profile) {
6081
6216
  out += " profile " + c.profile + "\n";
6082
6217
  }
6218
+ for (const v of c.variants ?? []) {
6219
+ out += dumpVariant(v);
6220
+ }
6083
6221
  for (const src of c.sourceRefs ?? (c.sourceRef && (c.sourceRef.doc || c.sourceRef.clause) ? [c.sourceRef] : [])) {
6084
6222
  out += dumpSourceRefAsRef(src, " ", escapeString);
6085
6223
  }
@@ -8452,7 +8590,7 @@ var VALID_SERIES_REDUCTIONS = [
8452
8590
  "worst_case",
8453
8591
  "max_abs_over_window"
8454
8592
  ];
8455
- function readIdList(block) {
8593
+ function readIdList2(block) {
8456
8594
  return tokenize(stripWrapping(block)).map(stripColon).map(stripWrapping).filter((s) => s.length > 0);
8457
8595
  }
8458
8596
  var parseVerdict = function(id, data) {
@@ -8492,7 +8630,7 @@ var parseVerdict = function(id, data) {
8492
8630
  } else if (keyword === "derive" || keyword === "expression") {
8493
8631
  result.derive = unwrapped(value);
8494
8632
  } else if (keyword === "inputs" || keyword === "uses") {
8495
- result.inputs = readIdList(value());
8633
+ result.inputs = readIdList2(value());
8496
8634
  } else if (keyword === "series_reduction") {
8497
8635
  const v = value();
8498
8636
  if (!VALID_SERIES_REDUCTIONS.includes(v)) {
@@ -9465,8 +9603,65 @@ var dumpTestPointSet = function(s) {
9465
9603
  return out;
9466
9604
  };
9467
9605
 
9606
+ // src/ser-des/config/commonTestCondition.ts
9607
+ var parseCommonTestCondition = (id, data) => {
9608
+ const condition = {
9609
+ id,
9610
+ title: "",
9611
+ reference: "",
9612
+ description: "",
9613
+ source: null
9614
+ };
9615
+ forEachEntry(
9616
+ data,
9617
+ (keyword, value) => {
9618
+ if (keyword === "title") {
9619
+ condition.title = stripWrapping(value());
9620
+ } else if (keyword === "reference") {
9621
+ condition.reference = stripWrapping(value());
9622
+ } else if (keyword === "description") {
9623
+ condition.description = stripWrapping(value());
9624
+ } else if (keyword === "source") {
9625
+ condition.source = readSource(unwrapBlock(value()));
9626
+ } else {
9627
+ return false;
9628
+ }
9629
+ return true;
9630
+ },
9631
+ { construct: "common_test_condition", id }
9632
+ );
9633
+ return (ctx) => {
9634
+ ctx.commonTestConditions[id] = condition;
9635
+ return ctx;
9636
+ };
9637
+ };
9638
+ var dumpCommonTestCondition = function(c) {
9639
+ let out = "common_test_condition " + c.id + " {\n";
9640
+ if (c.title) {
9641
+ out += ' title "' + escapeString(c.title) + '"\n';
9642
+ }
9643
+ if (c.reference) {
9644
+ out += ' reference "' + escapeString(c.reference) + '"\n';
9645
+ }
9646
+ if (c.description) {
9647
+ out += ' description "' + escapeString(c.description) + '"\n';
9648
+ }
9649
+ if (c.source && (c.source.doc || c.source.clause)) {
9650
+ out += " source {\n";
9651
+ if (c.source.doc) {
9652
+ out += ' doc "' + escapeString(c.source.doc) + '"\n';
9653
+ }
9654
+ if (c.source.clause) {
9655
+ out += ' clause "' + escapeString(c.source.clause) + '"\n';
9656
+ }
9657
+ out += " }\n";
9658
+ }
9659
+ out += "}\n";
9660
+ return out;
9661
+ };
9662
+
9468
9663
  // src/ser-des/config/requirement.ts
9469
- function readIdList2(block) {
9664
+ function readIdList3(block) {
9470
9665
  return tokenize(stripWrapping(block)).map(stripColon).map(stripWrapping).filter((s) => s.length > 0);
9471
9666
  }
9472
9667
  function readAccepts(block) {
@@ -9519,7 +9714,7 @@ function readLimit(block) {
9519
9714
  if (cmd === "expression") {
9520
9715
  limit.expression = stripWrapping(t[i++]);
9521
9716
  } else if (cmd === "uses") {
9522
- limit.uses = readIdList2(t[i++]);
9717
+ limit.uses = readIdList3(t[i++]);
9523
9718
  } else if (cmd === "modality") {
9524
9719
  limit.modality = stripWrapping(t[i++]);
9525
9720
  } else if (cmd === "relative_to") {
@@ -9658,7 +9853,7 @@ function readParameters(block) {
9658
9853
  }
9659
9854
  }
9660
9855
  } else if (pc === "enum_values") {
9661
- param.enumValues = readIdList2(pt[j++]);
9856
+ param.enumValues = readIdList3(pt[j++]);
9662
9857
  } else {
9663
9858
  unwrapBlock(pt[j++]);
9664
9859
  }
@@ -9702,7 +9897,7 @@ var parseRequirement = function(id, data) {
9702
9897
  } else if (cmd === "guidance") {
9703
9898
  result.guidance = stripWrapping(t[i++]);
9704
9899
  } else if (cmd === "binds_to") {
9705
- result.bindsTo = readIdList2(t[i++]);
9900
+ result.bindsTo = readIdList3(t[i++]);
9706
9901
  } else if (cmd === "subjects") {
9707
9902
  result.subjects = readSubjects(unwrapBlock(t[i++]));
9708
9903
  } else if (cmd === "parameters") {
@@ -9737,7 +9932,7 @@ var parseRequirement = function(id, data) {
9737
9932
  }
9738
9933
  }
9739
9934
  } else if (cmd === "dependencies") {
9740
- result.dependencies = readIdList2(t[i++]);
9935
+ result.dependencies = readIdList3(t[i++]);
9741
9936
  } else if (cmd === "source_discrepancy") {
9742
9937
  result.sourceDiscrepancy = parseSourceDiscrepancy(unwrapBlock(t[i++]));
9743
9938
  } else if (cmd === "source" || cmd === "reference") {
@@ -9951,9 +10146,9 @@ var parseRequirementClass = function(id, data) {
9951
10146
  } else if (cmd === "applicability") {
9952
10147
  result.applicability = parseApplicability(unwrapBlock(t[i++]));
9953
10148
  } else if (cmd === "dependencies") {
9954
- result.dependencies = readIdList2(t[i++]);
10149
+ result.dependencies = readIdList3(t[i++]);
9955
10150
  } else if (cmd === "reference") {
9956
- result.referenceIds = readIdList2(t[i++]);
10151
+ result.referenceIds = readIdList3(t[i++]);
9957
10152
  } else {
9958
10153
  i = skipUnknownValue(t, i, cmd);
9959
10154
  }
@@ -10658,7 +10853,7 @@ function dumpSource2(keyword, src, indent) {
10658
10853
  return `${indent}${keyword} { doc "${escapeString(src.doc)}" clause "${escapeString(src.clause)}"${frag} }
10659
10854
  `;
10660
10855
  }
10661
- function readIdList3(block) {
10856
+ function readIdList4(block) {
10662
10857
  return tokenize(stripWrapping(block)).map(stripColon).map(stripWrapping).filter((s) => s.length > 0);
10663
10858
  }
10664
10859
  function dumpIdList(keyword, ids, indent) {
@@ -10795,9 +10990,9 @@ var parseInstrument = function(id, data) {
10795
10990
  break;
10796
10991
  }
10797
10992
  if (fc === "dimensions") {
10798
- result.familyDefaultDimensions = readIdList3(ft[j++]);
10993
+ result.familyDefaultDimensions = readIdList4(ft[j++]);
10799
10994
  } else if (fc === "parameters") {
10800
- result.familyDefaultParameters = readIdList3(ft[j++]);
10995
+ result.familyDefaultParameters = readIdList4(ft[j++]);
10801
10996
  } else {
10802
10997
  unwrapBlock(ft[j++]);
10803
10998
  }
@@ -11021,7 +11216,7 @@ function parseDimensionValues(block) {
11021
11216
  } else if (cmd === "description") {
11022
11217
  value.description = stripWrapping(vt[j++]);
11023
11218
  } else if (cmd === "implies") {
11024
- value.implies = readIdList3(vt[j++]);
11219
+ value.implies = readIdList4(vt[j++]);
11025
11220
  } else if (cmd === "term_ref") {
11026
11221
  value.termRef = stripWrapping(vt[j++]);
11027
11222
  } else if (cmd === "payload") {
@@ -11151,9 +11346,9 @@ function parseModelGroup(block) {
11151
11346
  if (cmd === "definition") {
11152
11347
  mg.definition = stripWrapping(t[i++]);
11153
11348
  } else if (cmd === "identical_characteristics") {
11154
- mg.identicalCharacteristics = readIdList3(t[i++]);
11349
+ mg.identicalCharacteristics = readIdList4(t[i++]);
11155
11350
  } else if (cmd === "identical_attributes") {
11156
- mg.identicalAttributes = readIdList3(t[i++]);
11351
+ mg.identicalAttributes = readIdList4(t[i++]);
11157
11352
  } else if (cmd === "group_by") {
11158
11353
  mg.groupBy = stripWrapping(t[i++]);
11159
11354
  } else if (cmd === "note") {
@@ -11346,6 +11541,80 @@ var dumpInstrument = function(inst) {
11346
11541
  out += "}\n";
11347
11542
  return out;
11348
11543
  };
11544
+ function parsePairList(block) {
11545
+ const decl = {
11546
+ key: "",
11547
+ value: "",
11548
+ keyDimension: "",
11549
+ components: []
11550
+ };
11551
+ const t = tokenize(block);
11552
+ let i = 0;
11553
+ while (i < t.length) {
11554
+ const cmd = t[i++];
11555
+ if (i > t.length) {
11556
+ break;
11557
+ }
11558
+ if (cmd === "key") {
11559
+ decl.key = stripWrapping(t[i++]);
11560
+ } else if (cmd === "value") {
11561
+ decl.value = stripWrapping(t[i++]);
11562
+ } else if (cmd === "key_dimension") {
11563
+ decl.keyDimension = stripWrapping(t[i++]);
11564
+ } else if (cmd === "component") {
11565
+ const cid = stripWrapping(t[i++]);
11566
+ const component = { id: cid, name: "", source: null };
11567
+ if (i < t.length && t[i].startsWith("{")) {
11568
+ const et = tokenize(unwrapBlock(t[i++]));
11569
+ let j = 0;
11570
+ while (j < et.length) {
11571
+ const ec = et[j++];
11572
+ if (j >= et.length) {
11573
+ break;
11574
+ }
11575
+ if (ec === "name") {
11576
+ component.name = stripWrapping(et[j++]);
11577
+ } else if (ec === "source") {
11578
+ component.source = readSource(unwrapBlock(et[j++]));
11579
+ } else {
11580
+ unwrapBlock(et[j++]);
11581
+ }
11582
+ }
11583
+ }
11584
+ decl.components.push(component);
11585
+ } else {
11586
+ i = skipUnknownValue(t, i, cmd);
11587
+ }
11588
+ }
11589
+ return decl;
11590
+ }
11591
+ function dumpPairList(decl) {
11592
+ let out = " pair_list {\n";
11593
+ out += " key " + dumpBareSafe(decl.key) + "\n";
11594
+ out += " value " + dumpBareSafe(decl.value) + "\n";
11595
+ if (decl.keyDimension) {
11596
+ out += " key_dimension " + dumpBareSafe(decl.keyDimension) + "\n";
11597
+ }
11598
+ for (const c of decl.components) {
11599
+ out += " component " + dumpBareSafe(c.id) + " {\n";
11600
+ if (c.name) {
11601
+ out += ' name "' + escapeString(c.name) + '"\n';
11602
+ }
11603
+ if (c.source && (c.source.doc || c.source.clause)) {
11604
+ out += " source {\n";
11605
+ if (c.source.doc) {
11606
+ out += ' doc "' + escapeString(c.source.doc) + '"\n';
11607
+ }
11608
+ if (c.source.clause) {
11609
+ out += ' clause "' + escapeString(c.source.clause) + '"\n';
11610
+ }
11611
+ out += " }\n";
11612
+ }
11613
+ out += " }\n";
11614
+ }
11615
+ out += " }\n";
11616
+ return out;
11617
+ }
11349
11618
  var parseAttributeDefinition = function(id, data) {
11350
11619
  const result = {
11351
11620
  id,
@@ -11390,6 +11659,8 @@ var parseAttributeDefinition = function(id, data) {
11390
11659
  result.unit = stripWrapping(t[i++]);
11391
11660
  } else if (cmd === "value_type") {
11392
11661
  result.valueType = stripWrapping(t[i++]);
11662
+ } else if (cmd === "pair_list") {
11663
+ result.pairList = parsePairList(unwrapBlock(t[i++]));
11393
11664
  } else if (cmd === "origin") {
11394
11665
  result.origin = stripWrapping(t[i++]);
11395
11666
  } else if (cmd === "scope") {
@@ -11401,7 +11672,7 @@ var parseAttributeDefinition = function(id, data) {
11401
11672
  } else if (cmd === "enum") {
11402
11673
  result.enumRef = stripWrapping(t[i++]);
11403
11674
  } else if (cmd === "enum_values") {
11404
- result.enumValues = readIdList3(t[i++]);
11675
+ result.enumValues = readIdList4(t[i++]);
11405
11676
  } else if (cmd === "note") {
11406
11677
  result.note = stripWrapping(t[i++]);
11407
11678
  } else if (cmd === "irdi") {
@@ -11461,6 +11732,9 @@ var dumpAttributeDefinition = function(a) {
11461
11732
  if (a.valueType) {
11462
11733
  out += " value_type " + a.valueType + "\n";
11463
11734
  }
11735
+ if (a.pairList) {
11736
+ out += dumpPairList(a.pairList);
11737
+ }
11464
11738
  if (a.origin) {
11465
11739
  out += " origin " + a.origin + "\n";
11466
11740
  }
@@ -11518,11 +11792,11 @@ var parseCapability = function(id, data) {
11518
11792
  } else if (cmd === "abstract") {
11519
11793
  result.abstract = stripWrapping(t[i++]) === "true";
11520
11794
  } else if (cmd === "extends") {
11521
- result.extends = readIdList3(t[i++]);
11795
+ result.extends = readIdList4(t[i++]);
11522
11796
  } else if (cmd === "requires") {
11523
- result.requires = readIdList3(t[i++]);
11797
+ result.requires = readIdList4(t[i++]);
11524
11798
  } else if (cmd === "has_parameters") {
11525
- result.hasParameters = readIdList3(t[i++]);
11799
+ result.hasParameters = readIdList4(t[i++]);
11526
11800
  } else if (cmd === "satisfies_requirements") {
11527
11801
  result.satisfiesRequirements = readReference(t[i++]);
11528
11802
  } else if (cmd === "verified_by_tests" || cmd === "verified_by") {
@@ -12049,7 +12323,7 @@ function readPromises(block) {
12049
12323
  } else if (cmd === "statement") {
12050
12324
  p.statement = stripWrapping(inner[j++]);
12051
12325
  } else if (cmd === "verified_by") {
12052
- p.verifiedBy = readIdList3(inner[j++]);
12326
+ p.verifiedBy = readIdList4(inner[j++]);
12053
12327
  } else if (cmd === "source") {
12054
12328
  p.source = readSource(unwrapBlock(inner[j++]));
12055
12329
  } else {
@@ -12643,7 +12917,7 @@ var instanceConstruct = {
12643
12917
  };
12644
12918
 
12645
12919
  // src/ser-des/config/artifact.ts
12646
- function readIdList4(block) {
12920
+ function readIdList5(block) {
12647
12921
  return tokenize(stripWrapping(block)).map(stripColon).map(stripWrapping).filter((s) => s.length > 0);
12648
12922
  }
12649
12923
  function dumpIdList2(keyword, ids, indent) {
@@ -12704,7 +12978,7 @@ function readContractMedia(block) {
12704
12978
  break;
12705
12979
  }
12706
12980
  if (cmd === "kinds") {
12707
- m.kinds = readIdList4(inner[j++]);
12981
+ m.kinds = readIdList5(inner[j++]);
12708
12982
  } else if (cmd === "role") {
12709
12983
  m.role = stripWrapping(inner[j++]);
12710
12984
  } else {
@@ -12897,7 +13171,7 @@ var parseArtifactInstance = function(id, data) {
12897
13171
  } else if (cmd === "content") {
12898
13172
  result.content = readValueMap2(unwrapBlock(t[i++]));
12899
13173
  } else if (cmd === "links") {
12900
- result.links = readIdList4(t[i++]);
13174
+ result.links = readIdList5(t[i++]);
12901
13175
  } else if (cmd === "reference") {
12902
13176
  result.referenceIds = readReference3(t[i++]);
12903
13177
  } else {
@@ -16081,6 +16355,310 @@ var dumpInformativeAnnex = function(a) {
16081
16355
  return out;
16082
16356
  };
16083
16357
 
16358
+ // src/ser-des/config/partAnnex.ts
16359
+ var PART_ANNEX_OBLIGATIONS = ["normative", "informative"];
16360
+ var parsePartAnnex = (id, data) => {
16361
+ const annex = {
16362
+ id,
16363
+ letter: "",
16364
+ title: "",
16365
+ obligation: "",
16366
+ summary: "",
16367
+ realization: "",
16368
+ source: { doc: "", clause: "" }
16369
+ };
16370
+ forEachEntry(
16371
+ data,
16372
+ (keyword, value) => {
16373
+ if (keyword === "letter") {
16374
+ annex.letter = stripWrapping(value());
16375
+ } else if (keyword === "title") {
16376
+ annex.title = stripWrapping(value());
16377
+ } else if (keyword === "obligation") {
16378
+ const obligation = stripWrapping(value());
16379
+ if (!PART_ANNEX_OBLIGATIONS.includes(obligation)) {
16380
+ throw new Error(
16381
+ `Parsing error: part_annex. ID ${id}: Unknown obligation "${obligation}" (valid: ${PART_ANNEX_OBLIGATIONS.join(", ")})`
16382
+ );
16383
+ }
16384
+ annex.obligation = obligation;
16385
+ } else if (keyword === "summary") {
16386
+ annex.summary = stripWrapping(value());
16387
+ } else if (keyword === "realization") {
16388
+ annex.realization = stripWrapping(value());
16389
+ } else if (keyword === "source") {
16390
+ annex.source = readSource(unwrapBlock(value()));
16391
+ } else {
16392
+ return false;
16393
+ }
16394
+ return true;
16395
+ },
16396
+ { construct: "part_annex", id }
16397
+ );
16398
+ return (ctx) => {
16399
+ ctx.partAnnexes[id] = annex;
16400
+ return ctx;
16401
+ };
16402
+ };
16403
+ var dumpPartAnnex = function(a) {
16404
+ let out = "part_annex " + a.id + " {\n";
16405
+ if (a.letter) {
16406
+ out += ' letter "' + escapeString(a.letter) + '"\n';
16407
+ }
16408
+ if (a.title) {
16409
+ out += ' title "' + escapeString(a.title) + '"\n';
16410
+ }
16411
+ if (a.obligation) {
16412
+ out += " obligation " + dumpBareSafe(a.obligation) + "\n";
16413
+ }
16414
+ if (a.summary) {
16415
+ out += ' summary "' + escapeString(a.summary) + '"\n';
16416
+ }
16417
+ if (a.realization) {
16418
+ out += ' realization "' + escapeString(a.realization) + '"\n';
16419
+ }
16420
+ if (a.source.doc || a.source.clause) {
16421
+ out += " source {\n";
16422
+ if (a.source.doc) {
16423
+ out += ' doc "' + escapeString(a.source.doc) + '"\n';
16424
+ }
16425
+ if (a.source.clause) {
16426
+ out += ' clause "' + escapeString(a.source.clause) + '"\n';
16427
+ }
16428
+ out += " }\n";
16429
+ }
16430
+ out += "}\n";
16431
+ return out;
16432
+ };
16433
+
16434
+ // src/ser-des/config/storyline.ts
16435
+ function readRecordValue(token) {
16436
+ if (token.startsWith("{")) {
16437
+ return tokenize(unwrapBlock(token)).filter((s) => s.length > 0).map(coerceValueToken);
16438
+ }
16439
+ return coerceValueToken(token);
16440
+ }
16441
+ function readRecordFields(block) {
16442
+ const fields = {};
16443
+ const t = tokenize(block);
16444
+ let i = 0;
16445
+ while (i < t.length) {
16446
+ const key = t[i++];
16447
+ if (i >= t.length) {
16448
+ break;
16449
+ }
16450
+ fields[stripColon(key)] = readRecordValue(t[i++]);
16451
+ }
16452
+ return fields;
16453
+ }
16454
+ function dumpRecordFields(fields, indent) {
16455
+ let out = "";
16456
+ for (const [key, value] of Object.entries(fields)) {
16457
+ if (Array.isArray(value)) {
16458
+ out += indent + key + " { " + value.map(dumpScalarToken).join(" ") + " }\n";
16459
+ } else {
16460
+ out += indent + key + " " + dumpScalarToken(value) + "\n";
16461
+ }
16462
+ }
16463
+ return out;
16464
+ }
16465
+ function parseParticipants(block) {
16466
+ const sections = [];
16467
+ const t = tokenize(block);
16468
+ let i = 0;
16469
+ while (i < t.length) {
16470
+ const sid = stripWrapping(t[i++]);
16471
+ if (i >= t.length || !t[i].startsWith("{")) {
16472
+ break;
16473
+ }
16474
+ const section = { id: sid, entries: [] };
16475
+ const st = tokenize(unwrapBlock(t[i++]));
16476
+ let j = 0;
16477
+ while (j < st.length) {
16478
+ const eid = stripWrapping(st[j++]);
16479
+ if (j >= st.length || !st[j].startsWith("{")) {
16480
+ break;
16481
+ }
16482
+ section.entries.push({
16483
+ id: eid,
16484
+ fields: readRecordFields(unwrapBlock(st[j++]))
16485
+ });
16486
+ }
16487
+ sections.push(section);
16488
+ }
16489
+ return sections;
16490
+ }
16491
+ var parseDemoWorld = (id, data) => {
16492
+ const world = {
16493
+ id,
16494
+ standard: "",
16495
+ description: "",
16496
+ participants: []
16497
+ };
16498
+ forEachEntry(
16499
+ data,
16500
+ (keyword, value) => {
16501
+ if (keyword === "standard") {
16502
+ world.standard = stripWrapping(value());
16503
+ } else if (keyword === "description") {
16504
+ world.description = stripWrapping(value());
16505
+ } else if (keyword === "participants") {
16506
+ world.participants = parseParticipants(unwrapBlock(value()));
16507
+ } else {
16508
+ return false;
16509
+ }
16510
+ return true;
16511
+ },
16512
+ { construct: "demo_world", id }
16513
+ );
16514
+ return (ctx) => {
16515
+ ctx.demoWorlds[id] = world;
16516
+ return ctx;
16517
+ };
16518
+ };
16519
+ var dumpDemoWorld = function(w) {
16520
+ let out = "demo_world " + w.id + " {\n";
16521
+ if (w.standard) {
16522
+ out += " standard " + dumpBareSafe(w.standard) + "\n";
16523
+ }
16524
+ if (w.description) {
16525
+ out += ' description "' + escapeString(w.description) + '"\n';
16526
+ }
16527
+ if (w.participants.length > 0) {
16528
+ out += " participants {\n";
16529
+ for (const s of w.participants) {
16530
+ out += " " + dumpBareSafe(s.id) + " {\n";
16531
+ for (const e of s.entries) {
16532
+ out += " " + dumpBareSafe(e.id) + " {\n";
16533
+ out += dumpRecordFields(e.fields, " ");
16534
+ out += " }\n";
16535
+ }
16536
+ out += " }\n";
16537
+ }
16538
+ out += " }\n";
16539
+ }
16540
+ out += "}\n";
16541
+ return out;
16542
+ };
16543
+ function parseSubjectEntries(block) {
16544
+ const entries = [];
16545
+ const t = tokenize(block);
16546
+ let i = 0;
16547
+ while (i < t.length) {
16548
+ const kind = stripWrapping(t[i++]);
16549
+ if (i >= t.length) {
16550
+ break;
16551
+ }
16552
+ const eid = stripWrapping(t[i++]);
16553
+ const entry = { kind, id: eid, fields: {} };
16554
+ if (i < t.length && t[i].startsWith("{")) {
16555
+ entry.fields = readRecordFields(unwrapBlock(t[i++]));
16556
+ }
16557
+ entries.push(entry);
16558
+ }
16559
+ return entries;
16560
+ }
16561
+ var parseStoryline = (id, data) => {
16562
+ const storyline = {
16563
+ id,
16564
+ name: "",
16565
+ idPrefix: "",
16566
+ party: { laboratory: "", authority: "" },
16567
+ subject: [],
16568
+ records: [],
16569
+ notes: []
16570
+ };
16571
+ forEachEntry(
16572
+ data,
16573
+ (keyword, value, peek) => {
16574
+ if (keyword === "name") {
16575
+ storyline.name = stripWrapping(value());
16576
+ } else if (keyword === "id_prefix") {
16577
+ storyline.idPrefix = stripWrapping(value());
16578
+ } else if (keyword === "party") {
16579
+ const pt = tokenize(unwrapBlock(value()));
16580
+ for (let j = 0; j + 1 < pt.length; j += 2) {
16581
+ if (pt[j] === "laboratory") {
16582
+ storyline.party.laboratory = stripWrapping(pt[j + 1]);
16583
+ } else if (pt[j] === "authority") {
16584
+ storyline.party.authority = stripWrapping(pt[j + 1]);
16585
+ }
16586
+ }
16587
+ } else if (keyword === "subject") {
16588
+ storyline.subject = parseSubjectEntries(unwrapBlock(value()));
16589
+ } else if (keyword === "record") {
16590
+ const store = stripWrapping(value());
16591
+ const idHead = peek();
16592
+ if (idHead === void 0 || idHead.startsWith("{")) {
16593
+ throw new Error(
16594
+ `Parsing error: storyline. ID ${id}: record ${store} is missing its id and block`
16595
+ );
16596
+ }
16597
+ const rid = stripWrapping(value());
16598
+ const blockHead = peek();
16599
+ if (blockHead === void 0 || !blockHead.startsWith("{")) {
16600
+ throw new Error(
16601
+ `Parsing error: storyline. ID ${id}: record ${store} ${rid} is missing its block`
16602
+ );
16603
+ }
16604
+ storyline.records.push({
16605
+ store,
16606
+ id: rid,
16607
+ fields: readRecordFields(unwrapBlock(value()))
16608
+ });
16609
+ } else if (keyword === "note") {
16610
+ storyline.notes.push(stripWrapping(value()));
16611
+ } else {
16612
+ return false;
16613
+ }
16614
+ return true;
16615
+ },
16616
+ { construct: "storyline", id }
16617
+ );
16618
+ return (ctx) => {
16619
+ ctx.storylines[id] = storyline;
16620
+ return ctx;
16621
+ };
16622
+ };
16623
+ var dumpStoryline = function(s) {
16624
+ let out = "storyline " + s.id + " {\n";
16625
+ if (s.name) {
16626
+ out += ' name "' + escapeString(s.name) + '"\n';
16627
+ }
16628
+ if (s.idPrefix) {
16629
+ out += " id_prefix " + dumpBareSafe(s.idPrefix) + "\n";
16630
+ }
16631
+ if (s.party.laboratory || s.party.authority) {
16632
+ out += " party {";
16633
+ if (s.party.laboratory) {
16634
+ out += " laboratory " + dumpBareSafe(s.party.laboratory);
16635
+ }
16636
+ if (s.party.authority) {
16637
+ out += " authority " + dumpBareSafe(s.party.authority);
16638
+ }
16639
+ out += " }\n";
16640
+ }
16641
+ if (s.subject.length > 0) {
16642
+ out += " subject {\n";
16643
+ for (const e of s.subject) {
16644
+ out += " " + dumpBareSafe(e.kind) + " " + dumpBareSafe(e.id) + " {\n";
16645
+ out += dumpRecordFields(e.fields, " ");
16646
+ out += " }\n";
16647
+ }
16648
+ out += " }\n";
16649
+ }
16650
+ for (const r of s.records) {
16651
+ out += " record " + dumpBareSafe(r.store) + " " + dumpBareSafe(r.id) + " {\n";
16652
+ out += dumpRecordFields(r.fields, " ");
16653
+ out += " }\n";
16654
+ }
16655
+ for (const n of s.notes) {
16656
+ out += ' note "' + escapeString(n) + '"\n';
16657
+ }
16658
+ out += "}\n";
16659
+ return out;
16660
+ };
16661
+
16084
16662
  // src/ser-des/config/index.ts
16085
16663
  function defineConstruct(def) {
16086
16664
  return def;
@@ -16305,6 +16883,16 @@ var CONSTRUCTS = [
16305
16883
  resolve: resolveSymbol,
16306
16884
  dump: dumpSymbol
16307
16885
  }),
16886
+ // The symbol-annotation register (smart TODO.roadmap/40 batch 4) —
16887
+ // one note text applying to many symbols; rides right after the
16888
+ // symbols in the dump order.
16889
+ defineConstruct({
16890
+ keyword: "formula_note",
16891
+ field: "formulaNotes",
16892
+ takesID: true,
16893
+ parse: parseFormulaNote,
16894
+ dump: dumpFormulaNote
16895
+ }),
16308
16896
  defineConstruct({
16309
16897
  keyword: "calculation",
16310
16898
  field: "calculations",
@@ -16334,6 +16922,16 @@ var CONSTRUCTS = [
16334
16922
  parse: parseTestPointSet,
16335
16923
  dump: dumpTestPointSet
16336
16924
  }),
16925
+ // The model-wide common test-conditions register (smart
16926
+ // TODO.roadmap/40 batch 4) — one entry per condition; the citation
16927
+ // string stays free (the linker owns the citation semantics).
16928
+ defineConstruct({
16929
+ keyword: "common_test_condition",
16930
+ field: "commonTestConditions",
16931
+ takesID: true,
16932
+ parse: parseCommonTestCondition,
16933
+ dump: dumpCommonTestCondition
16934
+ }),
16337
16935
  defineConstruct({
16338
16936
  keyword: "competence_kind",
16339
16937
  field: "competenceKinds",
@@ -16526,6 +17124,34 @@ var CONSTRUCTS = [
16526
17124
  parse: parseInformativeAnnex,
16527
17125
  dump: dumpInformativeAnnex
16528
17126
  }),
17127
+ // The rec's own annex-volume index (smart TODO.roadmap/40 batch 4) —
17128
+ // NOT the external-guidance informative_annex; the normative/
17129
+ // informative obligation mark is the register's point.
17130
+ defineConstruct({
17131
+ keyword: "part_annex",
17132
+ field: "partAnnexes",
17133
+ takesID: true,
17134
+ parse: parsePartAnnex,
17135
+ dump: dumpPartAnnex
17136
+ }),
17137
+ // The demo seeds (smart TODO.roadmap/40 batch 4) — one demo_world per
17138
+ // package (file-level metadata + the OPEN participants registry) and
17139
+ // one storyline per flow; the record-value sub-grammar follows the
17140
+ // quantity.ts dumpScalarToken conventions.
17141
+ defineConstruct({
17142
+ keyword: "demo_world",
17143
+ field: "demoWorlds",
17144
+ takesID: true,
17145
+ parse: parseDemoWorld,
17146
+ dump: dumpDemoWorld
17147
+ }),
17148
+ defineConstruct({
17149
+ keyword: "storyline",
17150
+ field: "storylines",
17151
+ takesID: true,
17152
+ parse: parseStoryline,
17153
+ dump: dumpStoryline
17154
+ }),
16529
17155
  // Primmel v3 twin interface (TODO.roadmap/32 — doctrine ch. 14 §14.4):
16530
17156
  // the connector-profile registry. Endpoints and serve bindings are NOT
16531
17157
  // top-level constructs — they are subject anatomy slots (is.endpoints /
@@ -16890,10 +17516,12 @@ var MERGE_FIELDS = [
16890
17516
  "forms",
16891
17517
  "subforms",
16892
17518
  "symbols",
17519
+ "formulaNotes",
16893
17520
  "calculations",
16894
17521
  "verdicts",
16895
17522
  "referenceMaterials",
16896
17523
  "testPointSets",
17524
+ "commonTestConditions",
16897
17525
  "competenceKinds",
16898
17526
  // The ISO/IEC 17067 scheme-type register (smart TODO.roadmap/40 batch
16899
17527
  // 2) composes like every register — the scheme-side packages resolve
@@ -16950,6 +17578,9 @@ var MERGE_FIELDS = [
16950
17578
  // batch 2) compose like the framework registers they sit beside.
16951
17579
  "documentModules",
16952
17580
  "informativeAnnexes",
17581
+ "partAnnexes",
17582
+ "demoWorlds",
17583
+ "storylines",
16953
17584
  // The pre-existing drift closed (the packages-as-SSOT epic): these
16954
17585
  // collections existed as constructs but were never merged, so `uses`
16955
17586
  // composition silently dropped them — comments, predicates, the
@@ -17823,10 +18454,12 @@ var TIER_BY_FIELD = {
17823
18454
  forms: "secondary",
17824
18455
  subforms: "secondary",
17825
18456
  symbols: "secondary",
18457
+ formulaNotes: "tertiary",
17826
18458
  calculations: "secondary",
17827
18459
  verdicts: "secondary",
17828
18460
  tables: "secondary",
17829
18461
  testPointSets: "secondary",
18462
+ commonTestConditions: "tertiary",
17830
18463
  referenceMaterials: "secondary",
17831
18464
  processes: "tertiary",
17832
18465
  // Process models (smart TODO.roadmap/40 batch 2) are tertiary beside
@@ -17857,6 +18490,9 @@ var TIER_BY_FIELD = {
17857
18490
  // module — annotation about the document set, not machinery inside
17858
18491
  // the model.
17859
18492
  informativeAnnexes: "cross-cutting",
18493
+ partAnnexes: "cross-cutting",
18494
+ demoWorlds: "tertiary",
18495
+ storylines: "tertiary",
17860
18496
  // Invariants (smart gap-close E9) are cross-cutting beside notes: the
17861
18497
  // typed replacement for the note-family encoding — doctrine about the
17862
18498
  // model, not machinery inside it (the enforcement claims point at the
@@ -18991,6 +19627,90 @@ var CHECK_RULES = [
18991
19627
  "normal",
18992
19628
  "smart TODO.roadmap/40 batch 2 (the packages-as-SSOT epic)"
18993
19629
  ),
19630
+ // C124 (smart TODO.roadmap/40 batch 4; the packages-as-SSOT epic): the
19631
+ // attribute_definition pair_list block's declaration shape — the key
19632
+ // and value slots are required, component ids are unique within the
19633
+ // block, and the key_dimension names a declared applicability
19634
+ // dimension when the dimension register is in composition scope
19635
+ // (per-register gating, the C58 doctrine). The closed-registry-over-
19636
+ // values leg quantifies over app-side records and stays app-side.
19637
+ R(
19638
+ "C124",
19639
+ "pair-list-shape",
19640
+ "base",
19641
+ "error",
19642
+ "normal",
19643
+ "smart TODO.roadmap/40 batch 4 (the packages-as-SSOT epic)"
19644
+ ),
19645
+ // C125 (smart TODO.roadmap/40 batch 4; the packages-as-SSOT epic): the
19646
+ // calculation variant block's declaration shape — variant ids unique
19647
+ // within the owning calculation, and the type-conditional facets
19648
+ // present (expression ⇒ expression, table_lookup ⇒ lookup,
19649
+ // profile_lookup ⇒ profile; the top-level shape discipline mirrored
19650
+ // onto the realization). The variant's params are engine call-site
19651
+ // names and deliberately carry NO params-resolve leg.
19652
+ R(
19653
+ "C125",
19654
+ "formula-variant-shape",
19655
+ "base",
19656
+ "error",
19657
+ "normal",
19658
+ "smart TODO.roadmap/40 batch 4 (the packages-as-SSOT epic)"
19659
+ ),
19660
+ // C126 (smart TODO.roadmap/40 batch 4; the packages-as-SSOT epic): the
19661
+ // formula_note register's reverse applicability resolves — every
19662
+ // applies_to entry names a declared symbol when the symbol register is
19663
+ // in composition scope (per-register gating, the C58 doctrine).
19664
+ R(
19665
+ "C126",
19666
+ "formula-note-targets-resolve",
19667
+ "composition",
19668
+ "error",
19669
+ "normal",
19670
+ "smart TODO.roadmap/40 batch 4 (the packages-as-SSOT epic)"
19671
+ ),
19672
+ // C127 (smart TODO.roadmap/40 batch 4; the packages-as-SSOT epic): the
19673
+ // common_test_condition register's declaration shape — the description
19674
+ // is required (the one facet both YAML shapes carry); the title stays
19675
+ // optional (the r91 keyed-map entries carry none) and the reference a
19676
+ // free citation string (no kernel leg — the linker owns the citation
19677
+ // semantics).
19678
+ R(
19679
+ "C127",
19680
+ "common-test-condition-shape",
19681
+ "base",
19682
+ "error",
19683
+ "normal",
19684
+ "smart TODO.roadmap/40 batch 4 (the packages-as-SSOT epic)"
19685
+ ),
19686
+ // C128 (smart TODO.roadmap/40 batch 4; the packages-as-SSOT epic): the
19687
+ // part_annex register's declaration shape — letters unique per package
19688
+ // (the index keys on the printed letter) and the source provenance
19689
+ // required; the obligation vocabulary is parse-enforced upstream and
19690
+ // carries no check leg.
19691
+ R(
19692
+ "C128",
19693
+ "part-annex-shape",
19694
+ "base",
19695
+ "error",
19696
+ "normal",
19697
+ "smart TODO.roadmap/40 batch 4 (the packages-as-SSOT epic)"
19698
+ ),
19699
+ // C129 (smart TODO.roadmap/40 batch 4; the packages-as-SSOT epic): the
19700
+ // demo-seed shapes — the storyline's id_prefix pattern (register-free),
19701
+ // the party laboratory/authority → the demo_world participant seeds
19702
+ // (gated on that register), the record stores → the entity-class stores
19703
+ // (gated), and the in-construct record cross-references (a record field
19704
+ // keyed by a sibling record's store names a sibling of that store —
19705
+ // ungated). Field-level discipline stays app-side.
19706
+ R(
19707
+ "C129",
19708
+ "storyline-shape",
19709
+ "composition",
19710
+ "error",
19711
+ "normal",
19712
+ "smart TODO.roadmap/40 batch 4 (the packages-as-SSOT epic)"
19713
+ ),
18994
19714
  // ── quantities / time / duality (TODO.roadmap/06) ─────────────────
18995
19715
  R(
18996
19716
  "C32",
@@ -23694,6 +24414,169 @@ function checkPackage(dir, options = {}) {
23694
24414
  }
23695
24415
  }
23696
24416
  }
24417
+ for (const a of standard.attributeDefinitions ?? []) {
24418
+ const pl = a.pairList;
24419
+ if (!pl) {
24420
+ continue;
24421
+ }
24422
+ const where = `attribute_definition ${a.id}: pair_list`;
24423
+ if (!pl.key) {
24424
+ err("C124", `${where}: the key slot is required (pair-list-shape)`);
24425
+ }
24426
+ if (!pl.value) {
24427
+ err("C124", `${where}: the value slot is required (pair-list-shape)`);
24428
+ }
24429
+ const seen = /* @__PURE__ */ new Set();
24430
+ for (const c of pl.components) {
24431
+ if (seen.has(c.id)) {
24432
+ err(
24433
+ "C124",
24434
+ `${where}: component "${c.id}" is declared twice (pair-list-shape)`
24435
+ );
24436
+ }
24437
+ seen.add(c.id);
24438
+ }
24439
+ if (pl.keyDimension && dimIds.size > 0 && !dimIds.has(pl.keyDimension)) {
24440
+ err(
24441
+ "C124",
24442
+ `${where}: key_dimension "${pl.keyDimension}" is not a declared applicability dimension (pair-list-shape)`
24443
+ );
24444
+ }
24445
+ }
24446
+ for (const c of standard.calculations ?? []) {
24447
+ const seen = /* @__PURE__ */ new Set();
24448
+ for (const v of c.variants ?? []) {
24449
+ const where = `calculation ${c.id}: variant ${v.id}`;
24450
+ if (seen.has(v.id)) {
24451
+ err(
24452
+ "C125",
24453
+ `${where}: the variant id is declared twice (formula-variant-shape)`
24454
+ );
24455
+ }
24456
+ seen.add(v.id);
24457
+ if (v.type === "expression" && !v.expression) {
24458
+ err(
24459
+ "C125",
24460
+ `${where}: type expression requires the expression facet (formula-variant-shape)`
24461
+ );
24462
+ }
24463
+ if (v.type === "table_lookup" && !v.lookup) {
24464
+ err(
24465
+ "C125",
24466
+ `${where}: type table_lookup requires the lookup block (formula-variant-shape)`
24467
+ );
24468
+ }
24469
+ if (v.type === "profile_lookup" && !v.profile) {
24470
+ err(
24471
+ "C125",
24472
+ `${where}: type profile_lookup requires the profile facet (formula-variant-shape)`
24473
+ );
24474
+ }
24475
+ }
24476
+ }
24477
+ if (symbolIds.size > 0) {
24478
+ for (const n of standard.formulaNotes ?? []) {
24479
+ for (const s of n.appliesTo ?? []) {
24480
+ if (!symbolIds.has(s)) {
24481
+ err(
24482
+ "C126",
24483
+ `formula_note ${n.id}: applies_to "${s}" is not a declared symbol (formula-note-targets-resolve)`
24484
+ );
24485
+ }
24486
+ }
24487
+ }
24488
+ }
24489
+ for (const c of standard.commonTestConditions ?? []) {
24490
+ if (!c.description) {
24491
+ err(
24492
+ "C127",
24493
+ `common_test_condition ${c.id}: the description is required \u2014 a condition entry carries its normative text (common-test-condition-shape)`
24494
+ );
24495
+ }
24496
+ }
24497
+ {
24498
+ const seenLetters = /* @__PURE__ */ new Map();
24499
+ for (const a of standard.partAnnexes ?? []) {
24500
+ if (a.letter) {
24501
+ const prior = seenLetters.get(a.letter);
24502
+ if (prior !== void 0) {
24503
+ err(
24504
+ "C128",
24505
+ `part_annex ${a.id}: letter "${a.letter}" is already declared by ${prior} \u2014 the annex-volume index keys on the printed letter (part-annex-shape)`
24506
+ );
24507
+ } else {
24508
+ seenLetters.set(a.letter, a.id);
24509
+ }
24510
+ }
24511
+ if (!a.source?.doc) {
24512
+ err(
24513
+ "C128",
24514
+ `part_annex ${a.id}: the source provenance is required \u2014 a documentary register entry cites its part (part-annex-shape)`
24515
+ );
24516
+ }
24517
+ }
24518
+ }
24519
+ {
24520
+ const participantSeeds = /* @__PURE__ */ new Set();
24521
+ for (const w of standard.demoWorlds ?? []) {
24522
+ for (const section of w.participants ?? []) {
24523
+ for (const e of section.entries ?? []) {
24524
+ participantSeeds.add(e.id);
24525
+ }
24526
+ }
24527
+ }
24528
+ const entityStores = new Set(
24529
+ (standard.dataclasses ?? []).map((c) => c.store).filter((s) => !!s)
24530
+ );
24531
+ for (const s of standard.storylines ?? []) {
24532
+ const where = `storyline ${s.id}`;
24533
+ if (s.idPrefix && !/^[a-z0-9-]+$/.test(s.idPrefix)) {
24534
+ err(
24535
+ "C129",
24536
+ `${where}: id_prefix "${s.idPrefix}" does not match ^[a-z0-9-]+$ \u2014 the id-minting prefix is a lowercase slug (storyline-shape)`
24537
+ );
24538
+ }
24539
+ if (participantSeeds.size > 0) {
24540
+ for (const [slot, ref] of [
24541
+ ["laboratory", s.party.laboratory],
24542
+ ["authority", s.party.authority]
24543
+ ]) {
24544
+ if (ref && !participantSeeds.has(ref)) {
24545
+ err(
24546
+ "C129",
24547
+ `${where}: party ${slot} "${ref}" is not a declared participant seed (storyline-shape)`
24548
+ );
24549
+ }
24550
+ }
24551
+ }
24552
+ const siblingStores = /* @__PURE__ */ new Map();
24553
+ for (const r of s.records ?? []) {
24554
+ if (entityStores.size > 0 && !entityStores.has(r.store)) {
24555
+ err(
24556
+ "C129",
24557
+ `${where}: record store "${r.store}" is not a declared entity-class store (storyline-shape)`
24558
+ );
24559
+ }
24560
+ let ids = siblingStores.get(r.store);
24561
+ if (!ids) {
24562
+ ids = /* @__PURE__ */ new Set();
24563
+ siblingStores.set(r.store, ids);
24564
+ }
24565
+ ids.add(r.id);
24566
+ }
24567
+ for (const r of s.records ?? []) {
24568
+ for (const [key, value] of Object.entries(r.fields)) {
24569
+ const targets = siblingStores.get(key);
24570
+ if (targets !== void 0 && !Array.isArray(value) && !targets.has(String(value))) {
24571
+ err(
24572
+ "C129",
24573
+ `${where}: record ${r.store} ${r.id}: ${key} "${String(value)}" is not a sibling ${key} record of this storyline (storyline-shape)`
24574
+ );
24575
+ }
24576
+ }
24577
+ }
24578
+ }
24579
+ }
23697
24580
  for (const d of standard.duals ?? []) {
23698
24581
  if (d.attribute && !attrIds.has(d.attribute)) {
23699
24582
  err(