@primmel/primmel 1.14.0 → 1.16.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 (48) hide show
  1. package/dist/src/check-rules.d.ts.map +1 -1
  2. package/dist/src/check-rules.js +13 -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 +112 -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 +3 -0
  9. package/dist/src/model-diff.js.map +1 -1
  10. package/dist/src/ser-des/config/approval.d.ts.map +1 -1
  11. package/dist/src/ser-des/config/approval.js +56 -9
  12. package/dist/src/ser-des/config/approval.js.map +1 -1
  13. package/dist/src/ser-des/config/gateway.d.ts.map +1 -1
  14. package/dist/src/ser-des/config/gateway.js +57 -0
  15. package/dist/src/ser-des/config/gateway.js.map +1 -1
  16. package/dist/src/ser-des/config/index.d.ts.map +1 -1
  17. package/dist/src/ser-des/config/index.js +11 -0
  18. package/dist/src/ser-des/config/index.js.map +1 -1
  19. package/dist/src/ser-des/config/process.d.ts.map +1 -1
  20. package/dist/src/ser-des/config/process.js +80 -8
  21. package/dist/src/ser-des/config/process.js.map +1 -1
  22. package/dist/src/ser-des/config/workflowStage.d.ts +5 -0
  23. package/dist/src/ser-des/config/workflowStage.d.ts.map +1 -0
  24. package/dist/src/ser-des/config/workflowStage.js +96 -0
  25. package/dist/src/ser-des/config/workflowStage.js.map +1 -0
  26. package/dist/src/ser-des/package.d.ts.map +1 -1
  27. package/dist/src/ser-des/package.js +3 -0
  28. package/dist/src/ser-des/package.js.map +1 -1
  29. package/dist/src/ser-des/parse.d.ts.map +1 -1
  30. package/dist/src/ser-des/parse.js +2 -0
  31. package/dist/src/ser-des/parse.js.map +1 -1
  32. package/dist/src/ser-des/types.d.ts +2 -0
  33. package/dist/src/ser-des/types.d.ts.map +1 -1
  34. package/dist/src/types/Approval.d.ts +5 -0
  35. package/dist/src/types/Approval.d.ts.map +1 -1
  36. package/dist/src/types/Gateway.d.ts +22 -0
  37. package/dist/src/types/Gateway.d.ts.map +1 -1
  38. package/dist/src/types/Standard.d.ts +5 -0
  39. package/dist/src/types/Standard.d.ts.map +1 -1
  40. package/dist/src/types/WorkflowStage.d.ts +22 -0
  41. package/dist/src/types/WorkflowStage.d.ts.map +1 -0
  42. package/dist/src/types/WorkflowStage.js +37 -0
  43. package/dist/src/types/WorkflowStage.js.map +1 -0
  44. package/dist/src/types/process.d.ts +34 -0
  45. package/dist/src/types/process.d.ts.map +1 -1
  46. package/dist-browser/index.mjs +1179 -1100
  47. package/dist-cli/primmel.mjs +1855 -1549
  48. package/package.json +1 -1
@@ -261,6 +261,8 @@ function parse(mmelString, parsers, options = {}) {
261
261
  certificateTemplates: {},
262
262
  // The certification workflow step register (batch 3)
263
263
  workflowConfigs: {},
264
+ // The named pipeline stages (batch 5)
265
+ workflowStages: {},
264
266
  // The verification pathways (batch 3)
265
267
  verificationPathways: {},
266
268
  // The selection rules (batch 3)
@@ -589,1730 +591,1785 @@ function unwrapped(value) {
589
591
  return unwrapBlock(x);
590
592
  }
591
593
 
592
- // src/ser-des/config/approval.ts
593
- var parseApproval = function(id, data) {
594
- const result = {
595
- id,
596
- name: "",
597
- modality: "",
598
- actor: null,
599
- approver: null,
600
- records: [],
601
- ref: [],
602
- _relations: {
603
- actor: "",
604
- approver: "",
605
- records: [],
606
- ref: []
594
+ // src/ser-des/config/series.ts
595
+ function parseSeriesDecl(block) {
596
+ const decl = { axes: [], cellSymbol: "", cellUnit: "" };
597
+ const t = tokenize(block);
598
+ let i = 0;
599
+ while (i < t.length) {
600
+ const cmd = t[i++];
601
+ if (cmd !== "axis" && cmd !== "cell") {
602
+ if (i < t.length) {
603
+ unwrapBlock(t[i - 1]);
604
+ }
605
+ continue;
607
606
  }
608
- };
609
- forEachEntry(
610
- data,
611
- (keyword, value) => {
612
- if (keyword === "modality") {
613
- result.modality = value();
614
- } else if (keyword === "name") {
615
- result.name = unwrapped(value);
616
- } else if (keyword === "actor") {
617
- result._relations.actor = value();
618
- } else if (keyword === "approve_by") {
619
- result._relations.approver = value();
620
- } else if (keyword === "approval_record") {
621
- result._relations.records = tokenizePackage(value());
622
- } else if (keyword === "reference") {
623
- result._relations.ref = tokenizePackage(value());
624
- } else {
625
- return false;
607
+ if (cmd === "axis") {
608
+ const axis = {
609
+ id: stripWrapping(t[i++]),
610
+ unit: "",
611
+ type: "",
612
+ role: ""
613
+ };
614
+ if (i < t.length && t[i].startsWith("{")) {
615
+ const ablock = unwrapBlock(t[i++]);
616
+ const at = tokenize(ablock);
617
+ let j = 0;
618
+ while (j < at.length) {
619
+ const ac = at[j++];
620
+ if (j >= at.length) {
621
+ break;
622
+ }
623
+ if (ac === "unit") {
624
+ axis.unit = stripWrapping(at[j++]);
625
+ } else if (ac === "type") {
626
+ axis.type = stripWrapping(at[j++]);
627
+ } else if (ac === "role") {
628
+ axis.role = stripWrapping(at[j++]);
629
+ } else {
630
+ unwrapBlock(at[j++]);
631
+ }
632
+ }
633
+ }
634
+ decl.axes.push(axis);
635
+ } else {
636
+ const cblock = unwrapBlock(t[i++]);
637
+ const ct = tokenize(cblock);
638
+ let j = 0;
639
+ while (j < ct.length) {
640
+ const cc = ct[j++];
641
+ if (j >= ct.length) {
642
+ break;
643
+ }
644
+ if (cc === "symbol") {
645
+ decl.cellSymbol = stripWrapping(ct[j++]);
646
+ } else if (cc === "unit") {
647
+ decl.cellUnit = stripWrapping(ct[j++]);
648
+ } else {
649
+ unwrapBlock(ct[j++]);
650
+ }
626
651
  }
627
- return true;
628
- },
629
- { construct: "approval", id }
630
- );
631
- return (ctx) => {
632
- ctx.approvals[id] = result;
633
- return ctx;
634
- };
635
- };
636
- var resolveApproval = function(ctx, unresolved) {
637
- const { _relations, ...rest } = unresolved;
638
- const p = { ...rest, records: [], ref: [] };
639
- if (_relations.actor !== "") {
640
- p.actor = resolveFromContext(ctx, "roles", _relations.actor) ?? null;
641
- }
642
- if (_relations.approver !== "") {
643
- p.approver = resolveFromContext(ctx, "roles", _relations.approver) ?? null;
644
- }
645
- for (const id of _relations.records) {
646
- const r = resolveFromContext(ctx, "regs", id);
647
- if (r !== void 0) {
648
- p.records.push(r);
649
652
  }
650
653
  }
651
- for (const id of _relations.ref) {
652
- const r = resolveFromContext(ctx, "references", id);
653
- if (r !== void 0) {
654
- p.ref.push(r);
654
+ return decl;
655
+ }
656
+ function dumpSeriesDecl(decl) {
657
+ let out = "series { ";
658
+ for (const a of decl.axes) {
659
+ out += "axis " + a.id + " { ";
660
+ if (a.unit) {
661
+ out += 'unit "' + escapeString(a.unit) + '" ';
662
+ }
663
+ if (a.type) {
664
+ out += "type " + a.type + " ";
665
+ }
666
+ if (a.role) {
667
+ out += "role " + a.role + " ";
655
668
  }
669
+ out += "} ";
656
670
  }
657
- return p;
658
- };
659
- var dumpApproval = function(approval) {
660
- let out = "approval " + approval.id + " {\n";
661
- out += ' name "' + escapeString(approval.name) + '"\n';
662
- if (approval.actor !== null) {
663
- out += " actor " + approval.actor.id + "\n";
671
+ out += "cell { ";
672
+ if (decl.cellSymbol) {
673
+ out += "symbol " + decl.cellSymbol + " ";
664
674
  }
665
- out += " modality " + approval.modality + "\n";
666
- if (approval.approver !== null) {
667
- out += " approve_by " + approval.approver.id + "\n";
675
+ if (decl.cellUnit) {
676
+ out += 'unit "' + escapeString(decl.cellUnit) + '" ';
668
677
  }
669
- if (approval.records.length > 0) {
670
- out += " approval_record {\n";
671
- for (const dr of approval.records) {
672
- out += " " + dr.id + "\n";
678
+ out += "} }";
679
+ return out;
680
+ }
681
+
682
+ // src/ser-des/config/ref.ts
683
+ function parseRef(t, i, stripWrapping2, unwrapBlock2) {
684
+ const predicate = stripWrapping2(t[i++] ?? "");
685
+ const target = stripWrapping2(t[i++] ?? "");
686
+ const ref = { predicate, target };
687
+ if (i < t.length && t[i].startsWith("{")) {
688
+ const block = unwrapBlock2(t[i++]);
689
+ const m = /note\s+"([^"]*)"/.exec(block) ?? /note\s+(\S+)/.exec(block);
690
+ if (m) {
691
+ ref.note = m[1];
673
692
  }
674
- out += " }\n";
675
693
  }
676
- if (approval.ref.length > 0) {
677
- out += " reference {\n";
678
- for (const r of approval.ref) {
679
- out += " " + r.id + "\n";
680
- }
681
- out += " }\n";
694
+ return { ref, next: i };
695
+ }
696
+ function parseRefFromReaders(value, peek, stripWrapping2, unwrapBlock2) {
697
+ const parts = [value(), value()];
698
+ const next = peek();
699
+ if (next && next.startsWith("{")) {
700
+ parts.push(value());
701
+ }
702
+ return parseRef(parts, 0, stripWrapping2, unwrapBlock2).ref;
703
+ }
704
+ function dumpRefs(refs, indent, escapeString2) {
705
+ if (!refs || refs.length === 0) {
706
+ return "";
707
+ }
708
+ let out = "";
709
+ for (const r of refs) {
710
+ out += `${indent}ref ${r.predicate} "${escapeString2(r.target)}"`;
711
+ out += r.note ? ` {
712
+ ${indent} note "${escapeString2(r.note)}"
713
+ ${indent}}
714
+ ` : "\n";
682
715
  }
683
- out += "}\n";
684
716
  return out;
685
- };
686
-
687
- // src/ser-des/config/data.ts
688
- var parseEnum = (id, data) => {
689
- const result = {
690
- id,
691
- values: []
692
- };
693
- forEachEntry(
694
- data,
695
- (_vid, value) => {
696
- result.values.push(parseEnumValue(_vid, value()));
697
- return true;
698
- },
699
- { construct: "enum", id }
700
- );
701
- return (ctx) => {
702
- ctx.enums[id] = result;
703
- return ctx;
704
- };
705
- };
706
- var parseEnumValue = (id, data) => {
707
- const ev = {
708
- id,
709
- value: ""
710
- };
711
- forEachEntry(
712
- data,
713
- (command, value) => {
714
- if (command === "definition") {
715
- ev.value = unwrapped(value);
716
- } else {
717
- return false;
718
- }
719
- return true;
720
- },
721
- { construct: "enum value", id }
722
- );
723
- return ev;
724
- };
725
- var parseRegistry = function(id, data) {
726
- const result = {
727
- id,
728
- title: "",
729
- data: null,
730
- _relations: {
731
- data: ""
717
+ }
718
+ function refTargetToSourceRef(target) {
719
+ const m = /^(urn:[^#]+)(?:#(.+))?$/.exec(target);
720
+ if (!m) {
721
+ return null;
722
+ }
723
+ const anchor = m[2];
724
+ if (!anchor) {
725
+ return { doc: target, clause: "" };
726
+ }
727
+ if (anchor.startsWith("clause-")) {
728
+ const rest = anchor.slice("clause-".length);
729
+ const slash = rest.indexOf("/");
730
+ if (slash >= 0) {
731
+ return {
732
+ doc: m[1],
733
+ clause: rest.slice(0, slash),
734
+ fragment: rest.slice(slash + 1)
735
+ };
732
736
  }
733
- };
734
- forEachEntry(
735
- data,
736
- (command, value) => {
737
- if (command === "title") {
738
- result.title = unwrapped(value);
739
- } else if (command === "data_class") {
740
- result._relations.data = value();
741
- } else {
742
- return false;
743
- }
744
- return true;
745
- },
746
- { construct: "registry", id }
747
- );
748
- return (ctx) => {
749
- ctx.regs[id] = result;
750
- return ctx;
751
- };
752
- };
753
- var parseDataClass = function(id, data) {
754
- const result = {
755
- id,
756
- attributes: []
757
- };
758
- forEachAttribute(
759
- data,
760
- (basic, details) => {
761
- if (basic.startsWith("ref ")) {
762
- const m = basic.match(/^ref\s+(\S+)\s+"([^"]*)"$/);
763
- if (m) {
764
- const ref = { predicate: m[1], target: m[2] };
765
- if (details) {
766
- const noteMatch = /note\s+"([^"]*)"/.exec(details) ?? /note\s+(\S+)/.exec(details);
767
- if (noteMatch) {
768
- ref.note = noteMatch[1];
769
- }
770
- }
771
- result.ref ??= [];
772
- result.ref.push(ref);
773
- return;
774
- }
775
- }
776
- const head = basic.trim();
777
- if (head === "store") {
778
- result.store = details.trim();
779
- return;
780
- }
781
- if (head === "description") {
782
- result.description = stripWrapping(details.trim());
783
- return;
784
- }
785
- if (head === "indexes") {
786
- result.indexes = details.split(/\s+/).filter((x) => x.length > 0);
787
- return;
788
- }
789
- if (head === "helper") {
790
- result.helper = details.trim() === "true";
791
- return;
792
- }
793
- if (head === "extends") {
794
- result.extends = details.trim();
795
- return;
796
- }
797
- result.attributes.push(parseDataAttribute(head, details));
798
- },
799
- { construct: "class", id }
800
- );
801
- return (ctx) => {
802
- ctx.dataclasses[id] = result;
803
- return ctx;
804
- };
805
- };
806
- var parseDataAttribute = (basic, details) => {
807
- const result = {
808
- id: "",
809
- type: "",
810
- modality: "",
811
- cardinality: "",
812
- definition: "",
813
- ref: [],
814
- satisfy: [],
815
- _relations: {
816
- ref: []
817
- }
818
- };
819
- const cardMatch = basic.match(/^(.*?)\s*\[([\d*][^\]]*)\]\s*$/);
820
- if (cardMatch) {
821
- result.cardinality = cardMatch[2].trim();
822
- basic = cardMatch[1];
823
- }
824
- const colonIndex = basic.indexOf(":");
825
- if (colonIndex !== -1) {
826
- result.type = basic.substr(colonIndex + 1, basic.length - colonIndex - 1).trim();
827
- basic = basic.substr(0, colonIndex);
737
+ return { doc: m[1], clause: rest };
828
738
  }
829
- result.id = basic.trim();
830
- forEachEntry(
831
- details,
832
- (keyword, value) => {
833
- if (keyword === "modality") {
834
- result.modality = value();
835
- } else if (keyword === "definition") {
836
- result.definition = unwrapped(value);
837
- } else if (keyword === "reference") {
838
- result._relations.ref = tokenizePackage(value());
839
- } else if (keyword === "satisfy") {
840
- result.satisfy = tokenizePackage(value());
841
- } else if (keyword === "on_delete") {
842
- result.onDelete = value();
843
- } else if (keyword === "deprecated") {
844
- result.deprecated = value() === "true";
845
- } else if (keyword === "enum_values") {
846
- result.enumValues = tokenizePackage(value());
847
- } else if (keyword === "required") {
848
- result.required = value() === "true";
849
- } else if (keyword === "unit") {
850
- result.unit = unwrapped(value);
851
- } else if (keyword === "default") {
852
- result.defaultValue = unwrapped(value);
853
- } else {
854
- return false;
855
- }
739
+ return { doc: target, clause: "" };
740
+ }
741
+ function foldRefIntoLegacy(el, ref) {
742
+ if (ref.predicate === "derives-from") {
743
+ const roleChannel = el.fieldReferences ?? el.formReferences;
744
+ const hasProvenanceSlot = "source" in el || "sourceRef" in el || el.sourceRefs !== void 0;
745
+ if (roleChannel && !hasProvenanceSlot) {
746
+ roleChannel.push({ urn: ref.target, role: "source" });
856
747
  return true;
857
- },
858
- { construct: "data attribute", id: result.id }
859
- );
860
- return result;
861
- };
862
- var resolveDataClass = function(ctx, unresolved) {
863
- const attributes = unresolved.attributes.map((attr) => {
864
- const resolved = { ...attr, ref: [] };
865
- for (const id of attr._relations.ref) {
866
- const r = resolveFromContext(ctx, "references", id);
867
- if (r !== void 0) {
868
- resolved.ref.push(r);
869
- }
870
748
  }
871
- return resolved;
872
- });
873
- return {
874
- id: unresolved.id,
875
- attributes,
876
- ...unresolved.store !== void 0 ? { store: unresolved.store } : {},
877
- ...unresolved.indexes !== void 0 ? { indexes: unresolved.indexes } : {},
878
- ...unresolved.helper !== void 0 ? { helper: unresolved.helper } : {},
879
- ...unresolved.extends !== void 0 ? { extends: unresolved.extends } : {},
880
- ...unresolved.description !== void 0 ? { description: unresolved.description } : {},
881
- ...unresolved.ref !== void 0 ? { ref: unresolved.ref } : {}
882
- };
883
- };
884
- var resolveRegistry = function(ctx, unresolved) {
885
- const { _relations, ...rest } = unresolved;
886
- const p = { ...rest, data: null };
887
- if (_relations.data !== "") {
888
- const dc = resolveFromContext(
889
- ctx,
890
- "dataclasses",
891
- _relations.data
892
- );
893
- if (dc !== void 0) {
894
- p.data = dc;
749
+ const b = refTargetToSourceRef(ref.target);
750
+ if (!b) {
751
+ return false;
895
752
  }
753
+ (el.sourceRefs ??= []).push(b);
754
+ if ("source" in el && !el.source) {
755
+ el.source = b;
756
+ }
757
+ if ("sourceRef" in el && !el.sourceRef) {
758
+ el.sourceRef = b;
759
+ }
760
+ if ("reference" in el && !el.reference) {
761
+ el.reference = b.doc;
762
+ }
763
+ return true;
896
764
  }
897
- return p;
898
- };
899
- var dumpDataClass = function(dataclass) {
900
- let out = "class " + dataclass.id + " {\n";
901
- if (dataclass.store) {
902
- out += " store { " + dataclass.store + " }\n";
903
- }
904
- if (dataclass.description) {
905
- out += ' description { "' + escapeString(dataclass.description) + '" }\n';
906
- }
907
- if (dataclass.indexes && dataclass.indexes.length > 0) {
908
- out += " indexes { " + dataclass.indexes.join(" ") + " }\n";
909
- }
910
- if (dataclass.helper !== void 0) {
911
- out += " helper { " + dataclass.helper + " }\n";
912
- }
913
- if (dataclass.extends) {
914
- out += " extends { " + dataclass.extends + " }\n";
765
+ if (ref.predicate === "cites") {
766
+ if (el.fieldReferences) {
767
+ el.fieldReferences.push({ urn: ref.target, role: "reference" });
768
+ } else if (el.formReferences) {
769
+ el.formReferences.push({ urn: ref.target, role: "reference" });
770
+ } else if (el.referenceIds) {
771
+ el.referenceIds.push(ref.target);
772
+ }
773
+ return true;
915
774
  }
916
- if (dataclass.ref && dataclass.ref.length > 0) {
917
- for (const r of dataclass.ref) {
918
- out += " ref " + r.predicate + ' "' + escapeString(r.target) + '"';
919
- if (r.note) {
920
- out += ' { note "' + escapeString(r.note) + '" }';
921
- }
922
- out += "\n";
775
+ const CITATION_ROLES = [
776
+ "requirement",
777
+ "test-procedure",
778
+ "calculation",
779
+ "report-format",
780
+ "method"
781
+ ];
782
+ if (CITATION_ROLES.includes(ref.predicate)) {
783
+ const channel = el.fieldReferences ?? el.formReferences;
784
+ if (!channel) {
785
+ return false;
923
786
  }
787
+ channel.push({ urn: ref.target, role: ref.predicate });
788
+ return true;
924
789
  }
925
- for (const a of dataclass.attributes) {
926
- out += toDataAttributeModel(a);
790
+ return false;
791
+ }
792
+ function dumpSourceRefAsRef(src, indent, escapeString2) {
793
+ if (src.doc && src.doc.startsWith("urn:")) {
794
+ const anchor = `${src.doc}${src.clause ? "#clause-" + src.clause : ""}${src.fragment ? "/" + src.fragment : ""}`;
795
+ return `${indent}ref derives-from "${escapeString2(anchor)}"
796
+ `;
927
797
  }
928
- out += "}\n";
929
- return out;
930
- };
931
- var toDataAttributeModel = (attribute) => {
932
- let out = " " + attribute.id;
933
- if (attribute.type !== "") {
934
- out += ": " + attribute.type;
798
+ return `${indent}source { doc "${escapeString2(src.doc ?? "")}" clause "${escapeString2(String(src.clause ?? ""))}"` + (src.fragment ? ` fragment "${escapeString2(src.fragment)}"` : "") + " }\n";
799
+ }
800
+
801
+ // src/ser-des/config/correspondence.ts
802
+ function parseCorresponds(t, i, stripWrapping2) {
803
+ if (t[i] === void 0) {
804
+ throw new Error(
805
+ "Parsing error: corresponds: Expecting value for corresponds (the scheme and the concept)"
806
+ );
935
807
  }
936
- if (attribute.cardinality !== "") {
937
- out += "[" + attribute.cardinality + "]";
808
+ const scheme = stripWrapping2(t[i++]);
809
+ if (t[i] === void 0) {
810
+ throw new Error(
811
+ "Parsing error: corresponds: Expecting value for corresponds (the concept)"
812
+ );
938
813
  }
939
- out += " {\n";
940
- out += ' definition "' + escapeString(attribute.definition) + '"\n';
941
- if (attribute.modality !== "") {
942
- out += " modality " + attribute.modality + "\n";
943
- }
944
- if (attribute.onDelete) {
945
- out += " on_delete " + attribute.onDelete + "\n";
946
- }
947
- if (attribute.deprecated) {
948
- out += " deprecated true\n";
949
- }
950
- if (attribute.enumValues && attribute.enumValues.length > 0) {
951
- out += " enum_values { " + attribute.enumValues.join(" ") + " }\n";
952
- }
953
- if (attribute.required !== void 0) {
954
- out += " required " + (attribute.required ? "true" : "false") + "\n";
955
- }
956
- if (attribute.unit) {
957
- out += ' unit "' + escapeString(attribute.unit) + '"\n';
814
+ const corr = {
815
+ scheme,
816
+ concept: stripWrapping2(t[i++]),
817
+ projections: []
818
+ };
819
+ if (i < t.length && t[i].startsWith("{")) {
820
+ const block = unwrapBlock(t[i++]);
821
+ forEachEntry(
822
+ block,
823
+ (keyword, value, peek) => {
824
+ if (keyword === "projection") {
825
+ const codec = stripWrapping2(value());
826
+ const entries = [];
827
+ const next = peek();
828
+ if (next && next.startsWith("{")) {
829
+ forEachEntry(
830
+ unwrapBlock(value()),
831
+ (k, kv) => {
832
+ entries.push({ key: k, value: stripWrapping2(kv()) });
833
+ return true;
834
+ },
835
+ { construct: "corresponds.projection", id: codec }
836
+ );
837
+ }
838
+ corr.projections.push({ codec, entries });
839
+ return true;
840
+ }
841
+ return false;
842
+ },
843
+ { construct: "corresponds", id: corr.scheme }
844
+ );
958
845
  }
959
- if (attribute.defaultValue !== void 0) {
960
- out += ' default "' + escapeString(attribute.defaultValue) + '"\n';
846
+ return { corr, next: i };
847
+ }
848
+ function parseCorrespondsFromReaders(value, peek, stripWrapping2) {
849
+ const parts = [value(), value()];
850
+ const next = peek();
851
+ if (next && next.startsWith("{")) {
852
+ parts.push(value());
961
853
  }
962
- if (attribute.satisfy.length > 0) {
963
- out += " satisfy {\n";
964
- for (const s of attribute.satisfy) {
965
- out += " " + s + "\n";
966
- }
967
- out += " }\n";
854
+ return parseCorresponds(parts, 0, stripWrapping2).corr;
855
+ }
856
+ function dumpCorrespondences(corrs, indent, escapeString2, dumpBareSafe2) {
857
+ if (!corrs || corrs.length === 0) {
858
+ return "";
968
859
  }
969
- if (attribute.ref.length > 0) {
970
- out += " reference {\n";
971
- for (const r of attribute.ref) {
972
- out += " " + r.id + "\n";
860
+ let out = "";
861
+ for (const c of corrs) {
862
+ out += `${indent}corresponds ${dumpBareSafe2(c.scheme)} "${escapeString2(c.concept)}"`;
863
+ if (c.projections.length === 0) {
864
+ out += "\n";
865
+ continue;
973
866
  }
974
- out += " }\n";
975
- }
976
- out += " }\n";
977
- return out;
978
- };
979
- var dumpEnumValue = (ev) => {
980
- let out = " " + ev.id + " {\n";
981
- out += ' definition "' + escapeString(ev.value) + '"\n';
982
- out += " }\n";
983
- return out;
984
- };
985
- var dumpEnum = function(en) {
986
- let out = "enum " + en.id + " {\n";
987
- for (const v of en.values) {
988
- out += dumpEnumValue(v);
989
- }
990
- out += "}\n";
991
- return out;
992
- };
993
- var dumpRegistry = function(reg) {
994
- let out = "data_registry " + reg.id + " {\n";
995
- out += ' title "' + escapeString(reg.title) + '"\n';
996
- if (reg.data !== null) {
997
- out += " data_class " + reg.data.id + "\n";
998
- }
999
- out += "}\n";
1000
- return out;
1001
- };
1002
- var parseVariable = function(id, data) {
1003
- const result = {
1004
- id,
1005
- type: "",
1006
- definition: "",
1007
- description: ""
1008
- };
1009
- forEachEntry(
1010
- data,
1011
- (keyword, value) => {
1012
- if (keyword === "type") {
1013
- result.type = value();
1014
- } else if (keyword === "definition") {
1015
- result.definition = unwrapped(value);
1016
- } else if (keyword === "description") {
1017
- result.description = unwrapped(value);
1018
- } else {
1019
- return false;
867
+ out += " {\n";
868
+ for (const p of c.projections) {
869
+ out += `${indent} projection ${dumpBareSafe2(p.codec)} {`;
870
+ for (const e of p.entries) {
871
+ out += ` ${dumpBareSafe2(e.key)} ${dumpBareSafe2(e.value)}`;
1020
872
  }
1021
- return true;
1022
- },
1023
- { construct: "variable", id }
1024
- );
1025
- return (ctx) => {
1026
- ctx.variables[id] = result;
1027
- return ctx;
1028
- };
1029
- };
1030
- var dumpVariable = function(v) {
1031
- let out = "variable " + v.id + " {\n";
1032
- if (v.type !== "") {
1033
- out += " type " + v.type + "\n";
1034
- }
1035
- if (v.definition !== "") {
1036
- out += ' definition "' + escapeString(v.definition) + '"\n';
1037
- }
1038
- if (v.description !== "") {
1039
- out += ' description "' + escapeString(v.description) + '"\n';
873
+ out += " }\n";
874
+ }
875
+ out += `${indent}}
876
+ `;
1040
877
  }
1041
- out += "}\n";
1042
878
  return out;
1043
- };
879
+ }
1044
880
 
1045
- // src/ser-des/config/event.ts
1046
- var parseEndEvent = function(id, data) {
1047
- const result = {
1048
- id,
1049
- eventType: "end"
881
+ // src/ser-des/config/sourceDiscrepancy.ts
882
+ var VALID_RESOLUTIONS = ["follows_clause_x", "annotated_only"];
883
+ function parseSourceDiscrepancy(block) {
884
+ const sd = {
885
+ summary: "",
886
+ sources: [],
887
+ resolution: "",
888
+ rationale: ""
1050
889
  };
1051
- if (data !== "") {
1052
- const t = tokenizePackage(data);
1053
- if (t.length > 0) {
1054
- throw new Error(
1055
- `Parsing error: end_event. ID ${id}: Expecting empty body`
1056
- );
890
+ const t = tokenize(block);
891
+ let i = 0;
892
+ while (i < t.length) {
893
+ const cmd = t[i++];
894
+ if (i >= t.length) {
895
+ break;
1057
896
  }
1058
- }
1059
- return (ctx) => {
1060
- ctx.events[id] = result;
1061
- return ctx;
1062
- };
1063
- };
1064
- var parseSignalCatchEvent = function(id, data) {
1065
- const result = {
1066
- id,
1067
- eventType: "signalcatch",
1068
- signal: ""
1069
- };
1070
- if (data !== "") {
1071
- const t = tokenizePackage(data);
1072
- let i = 0;
1073
- while (i < t.length) {
1074
- const command = t[i++];
1075
- if (i < t.length) {
1076
- if (command === "catch") {
1077
- result.signal = unwrapBlock(t[i++]);
1078
- } else {
1079
- i++;
1080
- }
1081
- } else {
897
+ if (cmd === "summary") {
898
+ sd.summary = stripWrapping(t[i++]);
899
+ } else if (cmd === "sources") {
900
+ sd.sources = tokenize(stripWrapping(t[i++])).map(stripWrapping).filter((s) => s.length > 0);
901
+ } else if (cmd === "resolution") {
902
+ const r = stripWrapping(t[i++]);
903
+ if (!VALID_RESOLUTIONS.includes(r)) {
1082
904
  throw new Error(
1083
- `Parsing error: Signal Catch Event. ID ${id}: Expecting value for ${command}`
905
+ `Parsing error: source_discrepancy: Unknown resolution ${r} (valid: ${VALID_RESOLUTIONS.join(
906
+ ", "
907
+ )})`
1084
908
  );
1085
909
  }
910
+ sd.resolution = r;
911
+ } else if (cmd === "rationale") {
912
+ sd.rationale = stripWrapping(t[i++]);
913
+ } else {
914
+ unwrapBlock(t[i++]);
1086
915
  }
1087
916
  }
1088
- return (ctx) => {
1089
- ctx.events[id] = result;
1090
- return ctx;
1091
- };
1092
- };
1093
- var parseStartEvent = function(id, data) {
1094
- const result = {
1095
- id,
1096
- eventType: "start"
1097
- };
1098
- if (data !== "") {
1099
- const t = tokenizePackage(data);
1100
- if (t.length > 0) {
1101
- throw new Error(
1102
- `Parsing error: end_event. ID ${id}: Expecting empty body`
1103
- );
1104
- }
917
+ return sd;
918
+ }
919
+ function dumpSourceDiscrepancy(sd, indent) {
920
+ let out = indent + "source_discrepancy { ";
921
+ out += 'summary "' + escapeString(sd.summary) + '" ';
922
+ out += "sources { " + sd.sources.map((s) => '"' + escapeString(s) + '"').join(" ") + " } ";
923
+ out += "resolution " + sd.resolution + " ";
924
+ out += 'rationale "' + escapeString(sd.rationale) + '" ';
925
+ out += "}";
926
+ return out;
927
+ }
928
+
929
+ // src/ser-des/config/field-parser.ts
930
+ function readValueToken(t, i) {
931
+ const tok = t[i] ?? "";
932
+ if (!tok.startsWith("ocl{")) {
933
+ return { text: tok, next: i + 1 };
1105
934
  }
1106
- return (ctx) => {
1107
- ctx.events[id] = result;
1108
- return ctx;
1109
- };
1110
- };
1111
- var parseTimerEvent = function(id, data) {
1112
- const result = {
1113
- id,
1114
- eventType: "timer",
1115
- type: "",
1116
- para: ""
1117
- };
1118
- if (data !== "") {
1119
- const t = tokenizePackage(data);
1120
- let i = 0;
1121
- while (i < t.length) {
1122
- const command = t[i++];
1123
- if (i < t.length) {
1124
- if (command === "type") {
1125
- result.type = t[i++];
1126
- } else if (command === "para") {
1127
- result.para = unwrapBlock(t[i++]);
1128
- } else {
1129
- i++;
935
+ const delta = (s) => (s.match(/\{/g) || []).length - (s.match(/\}/g) || []).length;
936
+ let text = tok;
937
+ let depth = delta(tok);
938
+ let j = i + 1;
939
+ while (depth > 0 && j < t.length) {
940
+ const nt = t[j++];
941
+ depth += delta(nt);
942
+ text += " " + nt;
943
+ }
944
+ return { text, next: j };
945
+ }
946
+ function parseValueEntries(raw) {
947
+ const inner = raw.trim().replace(/^[[{]/, "").replace(/[\]}]$/, "");
948
+ const t = tokenizePackage(inner);
949
+ const out = [];
950
+ let i = 0;
951
+ while (i < t.length) {
952
+ const entry = stripWrapping(t[i++].replace(/,$/, ""));
953
+ if (!entry) {
954
+ continue;
955
+ }
956
+ if (i < t.length && t[i].startsWith("{")) {
957
+ const lb = tokenizePackage(unwrapBlock(t[i++]));
958
+ let label = "";
959
+ for (let k = 0; k + 1 < lb.length; k += 2) {
960
+ if (lb[k] === "label") {
961
+ label = stripWrapping(lb[k + 1]);
1130
962
  }
1131
- } else {
1132
- throw new Error(
1133
- `Parsing error: Timer Event. ID ${id}: Expecting value for ${command}`
1134
- );
1135
963
  }
964
+ out.push({ value: entry, label });
965
+ } else {
966
+ out.push(entry);
1136
967
  }
1137
968
  }
1138
- return (ctx) => {
1139
- ctx.events[id] = result;
1140
- return ctx;
1141
- };
1142
- };
1143
- var dumpEvent = function(event) {
1144
- if (event.eventType === "start") {
1145
- return dumpStartEvent(event);
1146
- }
1147
- if (event.eventType === "end") {
1148
- return dumpEndEvent(event);
1149
- }
1150
- if (event.eventType === "signalcatch") {
1151
- return dumpSignalCatchEvent(event);
1152
- }
1153
- if (event.eventType === "timer") {
1154
- return dumpTimerEvent(event);
1155
- }
1156
- return "";
1157
- };
1158
- function dumpEndEvent(end) {
1159
- return "end_event " + end.id + " {\n}\n";
969
+ return out;
1160
970
  }
1161
- function dumpSignalCatchEvent(sc) {
1162
- let out = "signal_catch_event " + sc.id + " {\n";
1163
- if (sc.signal !== "") {
1164
- out += ' catch "' + escapeString(sc.signal) + '"\n';
971
+ function dumpValueEntry(e) {
972
+ if (typeof e === "string") {
973
+ return e;
1165
974
  }
1166
- out += "}\n";
1167
- return out;
975
+ return e.value + ' { label "' + escapeString(e.label) + '" }';
1168
976
  }
1169
- function dumpStartEvent(s) {
1170
- return "start_event " + s.id + " {\n}\n";
977
+ function dumpBareSafe(v) {
978
+ return /[\s{}"]/.test(v) || v.endsWith(":") || v.startsWith("#") || v.startsWith("//") ? '"' + escapeString(v) + '"' : v;
1171
979
  }
1172
- function dumpTimerEvent(te) {
1173
- let out = "timer_event " + te.id + " {\n";
1174
- if (te.type !== "") {
1175
- out += " type " + te.type + "\n";
980
+ function stripColon(x) {
981
+ return x.endsWith(":") ? x.slice(0, -1) : x;
982
+ }
983
+ function readBalanced(t, i) {
984
+ const first = t[i] ?? "";
985
+ if (!first.startsWith("[")) {
986
+ return { text: first, next: i + 1 };
1176
987
  }
1177
- if (te.para !== "") {
1178
- out += ' para "' + escapeString(te.para) + '"\n';
988
+ let text = first;
989
+ let j = i + 1;
990
+ while (!text.includes("]") && j < t.length) {
991
+ text += " " + t[j++];
1179
992
  }
1180
- out += "}\n";
1181
- return out;
993
+ return { text, next: j };
1182
994
  }
1183
-
1184
- // src/ser-des/config/gateway.ts
1185
- var parseExclusiveGate = function(id, data) {
1186
- const gateway = {
1187
- id,
1188
- gatewayType: "exclusive_gateway",
1189
- label: ""
1190
- };
1191
- forEachEntry(
1192
- data,
1193
- (command, value) => {
1194
- if (command === "label") {
1195
- gateway.label = unwrapped(value);
1196
- } else {
1197
- return false;
1198
- }
1199
- return true;
1200
- },
1201
- { construct: "Exclusive gateway", id }
1202
- );
1203
- return (ctx) => {
1204
- ctx.gateways[id] = gateway;
1205
- return ctx;
1206
- };
1207
- };
1208
- var dumpGateway = function(gate) {
1209
- if (gate.gatewayType === "exclusive_gateway") {
1210
- return dumpEGate(gate);
1211
- }
1212
- return "";
1213
- };
1214
- function dumpEGate(egate) {
1215
- let out = "exclusive_gateway " + egate.id + " {\n";
1216
- if (egate.label !== "") {
1217
- out += ' label "' + escapeString(egate.label) + '"\n';
995
+ function subBlockTokens(block) {
996
+ return tokenizePackage(block).map((s) => s.replace(/^;+|;+$/g, "")).filter((s) => s.length > 0);
997
+ }
998
+ function readEntryTokens(value) {
999
+ if (value.startsWith("{")) {
1000
+ return subBlockTokens(unwrapBlock(value)).flatMap((s) => s.split(",")).map((s) => stripWrapping(s.trim())).filter((s) => s.length > 0);
1218
1001
  }
1219
- out += "}\n";
1220
- return out;
1002
+ const single = stripWrapping(value);
1003
+ return single === "" ? [] : [single];
1221
1004
  }
1222
-
1223
- // src/ser-des/config/metadata.ts
1224
- var parseMetadata = function(token) {
1225
- const metadata = {
1226
- schema: "",
1227
- author: "",
1228
- title: "",
1229
- edition: "",
1230
- namespace: "",
1231
- shortname: ""
1232
- };
1233
- if (token !== "") {
1234
- const t = tokenizePackage(token);
1235
- let i = 0;
1236
- while (i < t.length) {
1237
- const keyword = t[i++];
1238
- if (i < t.length) {
1239
- if (keyword === "title") {
1240
- metadata.title = stripWrapping(t[i++]);
1241
- } else if (keyword === "schema") {
1242
- metadata.schema = stripWrapping(t[i++]);
1243
- } else if (keyword === "edition") {
1244
- metadata.edition = stripWrapping(t[i++]);
1245
- } else if (keyword === "author") {
1246
- metadata.author = stripWrapping(t[i++]);
1247
- } else if (keyword === "namespace") {
1248
- metadata.namespace = stripWrapping(t[i++]);
1249
- } else if (keyword === "shortname") {
1250
- metadata.shortname = stripWrapping(t[i++]);
1251
- } else {
1252
- throw new Error(
1253
- "Parsing error: metadata. Unknown keyword " + keyword
1254
- );
1255
- }
1256
- } else {
1257
- throw new Error(
1258
- "Parsing error: metadata. Expecting value for " + keyword
1259
- );
1260
- }
1005
+ function readSource(block) {
1006
+ const src = { doc: "", clause: "" };
1007
+ const t = tokenize(block);
1008
+ let i = 0;
1009
+ while (i < t.length) {
1010
+ const cmd = t[i++];
1011
+ if (i >= t.length) {
1012
+ break;
1261
1013
  }
1262
- }
1263
- return (ctx) => {
1264
- ctx.metadata = metadata;
1265
- return ctx;
1266
- };
1267
- };
1268
-
1269
- // src/ser-des/config/ref.ts
1270
- function parseRef(t, i, stripWrapping2, unwrapBlock2) {
1271
- const predicate = stripWrapping2(t[i++] ?? "");
1272
- const target = stripWrapping2(t[i++] ?? "");
1273
- const ref = { predicate, target };
1274
- if (i < t.length && t[i].startsWith("{")) {
1275
- const block = unwrapBlock2(t[i++]);
1276
- const m = /note\s+"([^"]*)"/.exec(block) ?? /note\s+(\S+)/.exec(block);
1277
- if (m) {
1278
- ref.note = m[1];
1014
+ if (cmd === "doc") {
1015
+ src.doc = stripWrapping(t[i++]);
1016
+ } else if (cmd === "clause") {
1017
+ src.clause = stripWrapping(t[i++]);
1018
+ } else if (cmd === "fragment") {
1019
+ src.fragment = stripWrapping(t[i++]);
1020
+ } else {
1021
+ unwrapBlock(t[i++]);
1279
1022
  }
1280
1023
  }
1281
- return { ref, next: i };
1024
+ return src;
1282
1025
  }
1283
- function parseRefFromReaders(value, peek, stripWrapping2, unwrapBlock2) {
1284
- const parts = [value(), value()];
1285
- const next = peek();
1286
- if (next && next.startsWith("{")) {
1287
- parts.push(value());
1026
+ function readFieldHead(t, i) {
1027
+ const name = t[i++];
1028
+ if (name === void 0) {
1029
+ return null;
1288
1030
  }
1289
- return parseRef(parts, 0, stripWrapping2, unwrapBlock2).ref;
1290
- }
1291
- function dumpRefs(refs, indent, escapeString2) {
1292
- if (!refs || refs.length === 0) {
1293
- return "";
1031
+ let type = "";
1032
+ if (t[i] === ":") {
1033
+ i++;
1034
+ type = t[i++] ?? "";
1035
+ if (t[i] && t[i].startsWith("[") && t[i].endsWith("]")) {
1036
+ i++;
1037
+ }
1294
1038
  }
1295
- let out = "";
1296
- for (const r of refs) {
1297
- out += `${indent}ref ${r.predicate} "${escapeString2(r.target)}"`;
1298
- out += r.note ? ` {
1299
- ${indent} note "${escapeString2(r.note)}"
1300
- ${indent}}
1301
- ` : "\n";
1302
- }
1303
- return out;
1304
- }
1305
- function refTargetToSourceRef(target) {
1306
- const m = /^(urn:[^#]+)(?:#(.+))?$/.exec(target);
1307
- if (!m) {
1039
+ const blockToken = t[i++];
1040
+ if (blockToken === void 0 || !blockToken.startsWith("{")) {
1308
1041
  return null;
1309
1042
  }
1310
- const anchor = m[2];
1311
- if (!anchor) {
1312
- return { doc: target, clause: "" };
1043
+ return { name, type, block: unwrapBlock(blockToken), next: i };
1044
+ }
1045
+ function parseFormField(name, block, type) {
1046
+ const field = {
1047
+ name,
1048
+ type: type || "string",
1049
+ typeDeclared: !!type,
1050
+ label: "",
1051
+ definition: "",
1052
+ unit: "",
1053
+ symbol: "",
1054
+ verdict: "",
1055
+ targets: [],
1056
+ dimension: "",
1057
+ enumRef: "",
1058
+ pattern: "",
1059
+ required: false,
1060
+ requiredWhen: "",
1061
+ refs: [],
1062
+ measurementMethod: "",
1063
+ calculationId: null,
1064
+ calculationBindings: [],
1065
+ derivation: "",
1066
+ evaluation: null,
1067
+ values: [],
1068
+ trueLabel: "",
1069
+ falseLabel: "",
1070
+ enumValues: [],
1071
+ defaultValue: "",
1072
+ hasDefault: false,
1073
+ referenceIds: [],
1074
+ fieldReferences: [],
1075
+ specificationReference: "",
1076
+ applicability: [],
1077
+ sourceDiscrepancy: null,
1078
+ fields: [],
1079
+ itemsType: "",
1080
+ subformRef: null
1081
+ };
1082
+ if (!block || !block.trim()) {
1083
+ return field;
1313
1084
  }
1314
- if (anchor.startsWith("clause-")) {
1315
- const rest = anchor.slice("clause-".length);
1316
- const slash = rest.indexOf("/");
1317
- if (slash >= 0) {
1318
- return {
1319
- doc: m[1],
1320
- clause: rest.slice(0, slash),
1321
- fragment: rest.slice(slash + 1)
1322
- };
1085
+ const t = tokenize(block);
1086
+ let i = 0;
1087
+ while (i < t.length) {
1088
+ const cmd = t[i++];
1089
+ if (i >= t.length) {
1090
+ break;
1091
+ }
1092
+ if (cmd === "label") {
1093
+ field.label = stripWrapping(t[i++]);
1094
+ } else if (cmd === "definition") {
1095
+ field.definition = stripWrapping(t[i++]);
1096
+ } else if (cmd === "description") {
1097
+ field.description = stripWrapping(t[i++]);
1098
+ } else if (cmd === "type") {
1099
+ field.type = stripWrapping(t[i++]);
1100
+ field.typeDeclared = true;
1101
+ } else if (cmd === "unit") {
1102
+ field.unit = stripWrapping(t[i++]);
1103
+ } else if (cmd === "symbol") {
1104
+ field.symbol = stripWrapping(t[i++]);
1105
+ } else if (cmd === "verdict") {
1106
+ field.verdict = stripWrapping(t[i++]);
1107
+ } else if (cmd === "targets") {
1108
+ field.targets = tokenizePackage(t[i++]).map(stripWrapping);
1109
+ } else if (cmd === "dimension") {
1110
+ field.dimension = stripWrapping(t[i++]);
1111
+ } else if (cmd === "enum") {
1112
+ field.enumRef = stripWrapping(t[i++]);
1113
+ } else if (cmd === "pattern") {
1114
+ field.pattern = stripWrapping(t[i++]);
1115
+ } else if (cmd === "scope") {
1116
+ field.scope = stripWrapping(t[i++]);
1117
+ } else if (cmd === "examples") {
1118
+ field.examples = stripWrapping(t[i++]);
1119
+ } else if (cmd === "bind") {
1120
+ field.bind = stripWrapping(t[i++]);
1121
+ } else if (cmd === "required") {
1122
+ field.required = stripWrapping(t[i++]) === "true";
1123
+ } else if (cmd === "required_when") {
1124
+ const read = readValueToken(t, i);
1125
+ field.requiredWhen = stripWrapping(read.text);
1126
+ i = read.next;
1127
+ } else if (cmd === "measurement_method") {
1128
+ field.measurementMethod = stripWrapping(t[i++]);
1129
+ } else if (cmd === "calculation") {
1130
+ const read = readValueToken(t, i);
1131
+ field.calculationId = stripWrapping(read.text);
1132
+ i = read.next;
1133
+ } else if (cmd === "calculation_bindings") {
1134
+ field.calculationBindings = parseCalculationBindings(unwrapBlock(t[i++]));
1135
+ } else if (cmd === "derivation") {
1136
+ field.derivation = stripWrapping(t[i++]);
1137
+ } else if (cmd === "evaluation") {
1138
+ field.evaluation = parseEvaluation(unwrapBlock(t[i++]));
1139
+ } else if (cmd === "values") {
1140
+ const read = readBalanced(t, i);
1141
+ field.values = parseValueEntries(read.text);
1142
+ i = read.next;
1143
+ } else if (cmd === "default") {
1144
+ field.defaultValue = stripWrapping(t[i++]);
1145
+ field.hasDefault = true;
1146
+ } else if (cmd === "true_label") {
1147
+ field.trueLabel = stripWrapping(t[i++]);
1148
+ } else if (cmd === "false_label") {
1149
+ field.falseLabel = stripWrapping(t[i++]);
1150
+ } else if (cmd === "enum_values") {
1151
+ field.enumValues = parseValueEntries(t[i++]);
1152
+ } else if (cmd === "min_items") {
1153
+ const raw = stripWrapping(t[i++]);
1154
+ const n = parseInt(raw, 10);
1155
+ field.minItems = isNaN(n) ? raw : n;
1156
+ } else if (cmd === "max_items") {
1157
+ const raw = stripWrapping(t[i++]);
1158
+ const n = parseInt(raw, 10);
1159
+ field.maxItems = isNaN(n) ? raw : n;
1160
+ } else if (cmd === "items") {
1161
+ const iblock = unwrapBlock(t[i++]);
1162
+ const it = tokenize(iblock);
1163
+ const typeParts = [];
1164
+ let k = 0;
1165
+ while (k < it.length && it[k] !== "fields") {
1166
+ if (it[k] === "unit" && k + 1 < it.length) {
1167
+ field.itemsUnit = stripWrapping(it[k + 1]);
1168
+ k += 2;
1169
+ } else {
1170
+ typeParts.push(it[k++]);
1171
+ }
1172
+ }
1173
+ field.itemsType = typeParts.join(" ");
1174
+ if (it[k] === "fields") {
1175
+ k++;
1176
+ if (k < it.length) {
1177
+ field.fields = parseNestedFields(unwrapBlock(it[k]));
1178
+ }
1179
+ }
1180
+ } else if (cmd === "series") {
1181
+ field.series = parseSeriesDecl(unwrapBlock(t[i++]));
1182
+ } else if (cmd === "fields") {
1183
+ field.fields = parseNestedFields(unwrapBlock(t[i++]));
1184
+ } else if (cmd === "subform_ref") {
1185
+ const subformId = stripWrapping(t[i++]);
1186
+ const refBlock = i < t.length ? unwrapBlock(t[i++]) : "";
1187
+ field.subformRef = parseSubformRef(subformId, refBlock);
1188
+ if (!field.type || field.type === "string") {
1189
+ field.type = "array";
1190
+ }
1191
+ } else if (cmd === "reference") {
1192
+ field.referenceIds = tokenizePackage(t[i++]).map(stripWrapping);
1193
+ } else if (cmd === "references") {
1194
+ field.fieldReferences = parseRoleReferences(unwrapBlock(t[i++]));
1195
+ } else if (cmd === "ref") {
1196
+ const r = parseRef(t, i, stripWrapping, unwrapBlock);
1197
+ if (!foldRefIntoLegacy(field, r.ref)) {
1198
+ field.refs.push(r.ref);
1199
+ }
1200
+ i = r.next;
1201
+ } else if (cmd === "corresponds") {
1202
+ const cc = parseCorresponds(t, i, stripWrapping);
1203
+ (field.correspondences ??= []).push(cc.corr);
1204
+ i = cc.next;
1205
+ } else if (cmd === "specification_reference") {
1206
+ field.specificationReference = stripWrapping(t[i++]);
1207
+ } else if (cmd === "applicability") {
1208
+ field.applicability = parseApplicability(unwrapBlock(t[i++]));
1209
+ } else if (cmd === "source_discrepancy") {
1210
+ field.sourceDiscrepancy = parseSourceDiscrepancy(unwrapBlock(t[i++]));
1211
+ } else {
1212
+ unwrapBlock(t[i++]);
1323
1213
  }
1324
- return { doc: m[1], clause: rest };
1325
1214
  }
1326
- return { doc: target, clause: "" };
1215
+ return field;
1327
1216
  }
1328
- function foldRefIntoLegacy(el, ref) {
1329
- if (ref.predicate === "derives-from") {
1330
- const roleChannel = el.fieldReferences ?? el.formReferences;
1331
- const hasProvenanceSlot = "source" in el || "sourceRef" in el || el.sourceRefs !== void 0;
1332
- if (roleChannel && !hasProvenanceSlot) {
1333
- roleChannel.push({ urn: ref.target, role: "source" });
1334
- return true;
1217
+ function parseCalculationBindings(block) {
1218
+ const out = [];
1219
+ const t = tokenize(block);
1220
+ let i = 0;
1221
+ while (i < t.length) {
1222
+ const key = stripColon(t[i++]);
1223
+ if (i >= t.length) {
1224
+ break;
1335
1225
  }
1336
- const b = refTargetToSourceRef(ref.target);
1337
- if (!b) {
1338
- return false;
1226
+ if (t[i] === ":") {
1227
+ i++;
1339
1228
  }
1340
- (el.sourceRefs ??= []).push(b);
1341
- if ("source" in el && !el.source) {
1342
- el.source = b;
1229
+ if (i < t.length) {
1230
+ out.push({ inputName: key, pathExpr: stripWrapping(t[i++]) });
1343
1231
  }
1344
- if ("sourceRef" in el && !el.sourceRef) {
1345
- el.sourceRef = b;
1232
+ }
1233
+ return out;
1234
+ }
1235
+ function parseEvaluation(block) {
1236
+ const rule = { rule: "", condition: "", referenceId: null };
1237
+ const t = tokenize(block);
1238
+ let i = 0;
1239
+ while (i < t.length) {
1240
+ const cmd = t[i++];
1241
+ if (i >= t.length) {
1242
+ break;
1346
1243
  }
1347
- if ("reference" in el && !el.reference) {
1348
- el.reference = b.doc;
1244
+ if (cmd === "rule") {
1245
+ rule.rule = stripWrapping(t[i++]);
1246
+ } else if (cmd === "verdict") {
1247
+ rule.verdict = stripWrapping(t[i++]);
1248
+ } else if (cmd === "op") {
1249
+ rule.op = stripWrapping(t[i++]);
1250
+ } else if (cmd === "limit") {
1251
+ rule.limit = stripWrapping(t[i++]);
1252
+ } else if (cmd === "condition") {
1253
+ rule.condition = stripWrapping(t[i++]);
1254
+ } else if (cmd === "reference") {
1255
+ const ids = tokenizePackage(t[i++]).map(stripWrapping);
1256
+ rule.referenceId = ids[0] ?? null;
1257
+ } else if (cmd === "specification_reference") {
1258
+ rule.specificationReference = stripWrapping(t[i++]);
1259
+ } else if (cmd === "source_discrepancy") {
1260
+ rule.sourceDiscrepancy = parseSourceDiscrepancy(unwrapBlock(t[i++]));
1261
+ } else {
1262
+ unwrapBlock(t[i++]);
1349
1263
  }
1350
- return true;
1351
1264
  }
1352
- if (ref.predicate === "cites") {
1353
- if (el.fieldReferences) {
1354
- el.fieldReferences.push({ urn: ref.target, role: "reference" });
1355
- } else if (el.formReferences) {
1356
- el.formReferences.push({ urn: ref.target, role: "reference" });
1357
- } else if (el.referenceIds) {
1358
- el.referenceIds.push(ref.target);
1359
- }
1360
- return true;
1361
- }
1362
- const CITATION_ROLES = [
1363
- "requirement",
1364
- "test-procedure",
1365
- "calculation",
1366
- "report-format",
1367
- "method"
1368
- ];
1369
- if (CITATION_ROLES.includes(ref.predicate)) {
1370
- const channel = el.fieldReferences ?? el.formReferences;
1371
- if (!channel) {
1372
- return false;
1373
- }
1374
- channel.push({ urn: ref.target, role: ref.predicate });
1375
- return true;
1376
- }
1377
- return false;
1378
- }
1379
- function dumpSourceRefAsRef(src, indent, escapeString2) {
1380
- if (src.doc && src.doc.startsWith("urn:")) {
1381
- const anchor = `${src.doc}${src.clause ? "#clause-" + src.clause : ""}${src.fragment ? "/" + src.fragment : ""}`;
1382
- return `${indent}ref derives-from "${escapeString2(anchor)}"
1383
- `;
1384
- }
1385
- return `${indent}source { doc "${escapeString2(src.doc ?? "")}" clause "${escapeString2(String(src.clause ?? ""))}"` + (src.fragment ? ` fragment "${escapeString2(src.fragment)}"` : "") + " }\n";
1386
- }
1387
-
1388
- // src/ser-des/config/correspondence.ts
1389
- function parseCorresponds(t, i, stripWrapping2) {
1390
- if (t[i] === void 0) {
1391
- throw new Error(
1392
- "Parsing error: corresponds: Expecting value for corresponds (the scheme and the concept)"
1393
- );
1394
- }
1395
- const scheme = stripWrapping2(t[i++]);
1396
- if (t[i] === void 0) {
1397
- throw new Error(
1398
- "Parsing error: corresponds: Expecting value for corresponds (the concept)"
1399
- );
1400
- }
1401
- const corr = {
1402
- scheme,
1403
- concept: stripWrapping2(t[i++]),
1404
- projections: []
1405
- };
1406
- if (i < t.length && t[i].startsWith("{")) {
1407
- const block = unwrapBlock(t[i++]);
1408
- forEachEntry(
1409
- block,
1410
- (keyword, value, peek) => {
1411
- if (keyword === "projection") {
1412
- const codec = stripWrapping2(value());
1413
- const entries = [];
1414
- const next = peek();
1415
- if (next && next.startsWith("{")) {
1416
- forEachEntry(
1417
- unwrapBlock(value()),
1418
- (k, kv) => {
1419
- entries.push({ key: k, value: stripWrapping2(kv()) });
1420
- return true;
1421
- },
1422
- { construct: "corresponds.projection", id: codec }
1423
- );
1424
- }
1425
- corr.projections.push({ codec, entries });
1426
- return true;
1427
- }
1428
- return false;
1429
- },
1430
- { construct: "corresponds", id: corr.scheme }
1431
- );
1432
- }
1433
- return { corr, next: i };
1434
- }
1435
- function parseCorrespondsFromReaders(value, peek, stripWrapping2) {
1436
- const parts = [value(), value()];
1437
- const next = peek();
1438
- if (next && next.startsWith("{")) {
1439
- parts.push(value());
1440
- }
1441
- return parseCorresponds(parts, 0, stripWrapping2).corr;
1442
- }
1443
- function dumpCorrespondences(corrs, indent, escapeString2, dumpBareSafe2) {
1444
- if (!corrs || corrs.length === 0) {
1445
- return "";
1446
- }
1447
- let out = "";
1448
- for (const c of corrs) {
1449
- out += `${indent}corresponds ${dumpBareSafe2(c.scheme)} "${escapeString2(c.concept)}"`;
1450
- if (c.projections.length === 0) {
1451
- out += "\n";
1452
- continue;
1453
- }
1454
- out += " {\n";
1455
- for (const p of c.projections) {
1456
- out += `${indent} projection ${dumpBareSafe2(p.codec)} {`;
1457
- for (const e of p.entries) {
1458
- out += ` ${dumpBareSafe2(e.key)} ${dumpBareSafe2(e.value)}`;
1459
- }
1460
- out += " }\n";
1461
- }
1462
- out += `${indent}}
1463
- `;
1464
- }
1465
- return out;
1265
+ return rule;
1466
1266
  }
1467
-
1468
- // src/ser-des/config/series.ts
1469
- function parseSeriesDecl(block) {
1470
- const decl = { axes: [], cellSymbol: "", cellUnit: "" };
1267
+ function parseNestedFields(block) {
1268
+ const out = [];
1471
1269
  const t = tokenize(block);
1472
1270
  let i = 0;
1473
1271
  while (i < t.length) {
1474
1272
  const cmd = t[i++];
1475
- if (cmd !== "axis" && cmd !== "cell") {
1273
+ if (cmd !== "field") {
1476
1274
  if (i < t.length) {
1477
1275
  unwrapBlock(t[i - 1]);
1478
1276
  }
1479
1277
  continue;
1480
1278
  }
1481
- if (cmd === "axis") {
1482
- const axis = {
1483
- id: stripWrapping(t[i++]),
1484
- unit: "",
1485
- type: "",
1486
- role: ""
1487
- };
1488
- if (i < t.length && t[i].startsWith("{")) {
1489
- const ablock = unwrapBlock(t[i++]);
1490
- const at = tokenize(ablock);
1491
- let j = 0;
1492
- while (j < at.length) {
1493
- const ac = at[j++];
1494
- if (j >= at.length) {
1495
- break;
1496
- }
1497
- if (ac === "unit") {
1498
- axis.unit = stripWrapping(at[j++]);
1499
- } else if (ac === "type") {
1500
- axis.type = stripWrapping(at[j++]);
1501
- } else if (ac === "role") {
1502
- axis.role = stripWrapping(at[j++]);
1503
- } else {
1504
- unwrapBlock(at[j++]);
1505
- }
1506
- }
1507
- }
1508
- decl.axes.push(axis);
1509
- } else {
1510
- const cblock = unwrapBlock(t[i++]);
1511
- const ct = tokenize(cblock);
1512
- let j = 0;
1513
- while (j < ct.length) {
1514
- const cc = ct[j++];
1515
- if (j >= ct.length) {
1516
- break;
1517
- }
1518
- if (cc === "symbol") {
1519
- decl.cellSymbol = stripWrapping(ct[j++]);
1520
- } else if (cc === "unit") {
1521
- decl.cellUnit = stripWrapping(ct[j++]);
1522
- } else {
1523
- unwrapBlock(ct[j++]);
1524
- }
1525
- }
1526
- }
1527
- }
1528
- return decl;
1529
- }
1530
- function dumpSeriesDecl(decl) {
1531
- let out = "series { ";
1532
- for (const a of decl.axes) {
1533
- out += "axis " + a.id + " { ";
1534
- if (a.unit) {
1535
- out += 'unit "' + escapeString(a.unit) + '" ';
1536
- }
1537
- if (a.type) {
1538
- out += "type " + a.type + " ";
1539
- }
1540
- if (a.role) {
1541
- out += "role " + a.role + " ";
1279
+ const head = readFieldHead(t, i);
1280
+ if (!head) {
1281
+ break;
1542
1282
  }
1543
- out += "} ";
1544
- }
1545
- out += "cell { ";
1546
- if (decl.cellSymbol) {
1547
- out += "symbol " + decl.cellSymbol + " ";
1548
- }
1549
- if (decl.cellUnit) {
1550
- out += 'unit "' + escapeString(decl.cellUnit) + '" ';
1283
+ out.push(parseFormField(head.name, head.block, head.type || void 0));
1284
+ i = head.next;
1551
1285
  }
1552
- out += "} }";
1553
1286
  return out;
1554
1287
  }
1555
-
1556
- // src/ser-des/config/sourceDiscrepancy.ts
1557
- var VALID_RESOLUTIONS = ["follows_clause_x", "annotated_only"];
1558
- function parseSourceDiscrepancy(block) {
1559
- const sd = {
1560
- summary: "",
1561
- sources: [],
1562
- resolution: "",
1563
- rationale: ""
1564
- };
1288
+ function parseApplicability(block) {
1289
+ const entries = [];
1565
1290
  const t = tokenize(block);
1566
1291
  let i = 0;
1567
1292
  while (i < t.length) {
1568
- const cmd = t[i++];
1293
+ const dimension = stripColon(t[i++]);
1569
1294
  if (i >= t.length) {
1570
1295
  break;
1571
1296
  }
1572
- if (cmd === "summary") {
1573
- sd.summary = stripWrapping(t[i++]);
1574
- } else if (cmd === "sources") {
1575
- sd.sources = tokenize(stripWrapping(t[i++])).map(stripWrapping).filter((s) => s.length > 0);
1576
- } else if (cmd === "resolution") {
1577
- const r = stripWrapping(t[i++]);
1578
- if (!VALID_RESOLUTIONS.includes(r)) {
1579
- throw new Error(
1580
- `Parsing error: source_discrepancy: Unknown resolution ${r} (valid: ${VALID_RESOLUTIONS.join(
1581
- ", "
1582
- )})`
1583
- );
1584
- }
1585
- sd.resolution = r;
1586
- } else if (cmd === "rationale") {
1587
- sd.rationale = stripWrapping(t[i++]);
1588
- } else {
1589
- unwrapBlock(t[i++]);
1297
+ if (t[i] === ":") {
1298
+ i++;
1299
+ }
1300
+ if (i < t.length) {
1301
+ const read = readBalanced(t, i);
1302
+ i = read.next;
1303
+ const trimmed = read.text.trim();
1304
+ let entry;
1305
+ if (trimmed.startsWith("[")) {
1306
+ const inner = trimmed.slice(1, trimmed.lastIndexOf("]"));
1307
+ const values = inner.split(/[,\s]+/).filter((s) => s.length > 0);
1308
+ entry = { dimension, values, mapping: null, match: null };
1309
+ } else if (trimmed.startsWith("{")) {
1310
+ const inner = trimmed.slice(1, -1);
1311
+ const mapping = {};
1312
+ for (const pair of inner.split(/[,\n]+/).map((s) => s.trim()).filter((s) => s)) {
1313
+ const m = pair.match(/^(\w+)\s*:\s*(.+)$/);
1314
+ if (m) {
1315
+ mapping[m[1]] = m[2].trim();
1316
+ }
1317
+ }
1318
+ entry = { dimension, values: [], mapping, match: null };
1319
+ } else {
1320
+ entry = {
1321
+ dimension,
1322
+ values: [stripWrapping(trimmed)],
1323
+ mapping: null,
1324
+ match: null
1325
+ };
1326
+ }
1327
+ if (!entry.mapping && t[i] === "match") {
1328
+ i++;
1329
+ const mode = stripWrapping(t[i++] ?? "");
1330
+ if (mode !== "any" && mode !== "all" && mode !== "exact") {
1331
+ throw new Error(
1332
+ `Parsing error: applicability: Unknown match ${mode} (valid: any, all, exact)`
1333
+ );
1334
+ }
1335
+ entry.match = mode;
1336
+ }
1337
+ entries.push(entry);
1590
1338
  }
1591
1339
  }
1592
- return sd;
1593
- }
1594
- function dumpSourceDiscrepancy(sd, indent) {
1595
- let out = indent + "source_discrepancy { ";
1596
- out += 'summary "' + escapeString(sd.summary) + '" ';
1597
- out += "sources { " + sd.sources.map((s) => '"' + escapeString(s) + '"').join(" ") + " } ";
1598
- out += "resolution " + sd.resolution + " ";
1599
- out += 'rationale "' + escapeString(sd.rationale) + '" ';
1600
- out += "}";
1601
- return out;
1602
- }
1603
-
1604
- // src/ser-des/config/field-parser.ts
1605
- function readValueToken(t, i) {
1606
- const tok = t[i] ?? "";
1607
- if (!tok.startsWith("ocl{")) {
1608
- return { text: tok, next: i + 1 };
1609
- }
1610
- const delta = (s) => (s.match(/\{/g) || []).length - (s.match(/\}/g) || []).length;
1611
- let text = tok;
1612
- let depth = delta(tok);
1613
- let j = i + 1;
1614
- while (depth > 0 && j < t.length) {
1615
- const nt = t[j++];
1616
- depth += delta(nt);
1617
- text += " " + nt;
1618
- }
1619
- return { text, next: j };
1340
+ return entries;
1620
1341
  }
1621
- function parseValueEntries(raw) {
1622
- const inner = raw.trim().replace(/^[[{]/, "").replace(/[\]}]$/, "");
1623
- const t = tokenizePackage(inner);
1624
- const out = [];
1625
- let i = 0;
1626
- while (i < t.length) {
1627
- const entry = stripWrapping(t[i++].replace(/,$/, ""));
1628
- if (!entry) {
1629
- continue;
1630
- }
1631
- if (i < t.length && t[i].startsWith("{")) {
1632
- const lb = tokenizePackage(unwrapBlock(t[i++]));
1633
- let label = "";
1634
- for (let k = 0; k + 1 < lb.length; k += 2) {
1635
- if (lb[k] === "label") {
1636
- label = stripWrapping(lb[k + 1]);
1342
+ function parseSubformRef(subformId, block) {
1343
+ const ref = {
1344
+ subformId: stripWrapping(subformId),
1345
+ parameters: {},
1346
+ applicability: []
1347
+ };
1348
+ if (block && block.trim()) {
1349
+ const t = tokenize(block);
1350
+ let i = 0;
1351
+ while (i < t.length) {
1352
+ const cmd = t[i++];
1353
+ if (i < t.length) {
1354
+ if (cmd === "parameters") {
1355
+ const pblock = unwrapBlock(t[i++]);
1356
+ const pt = tokenize(pblock);
1357
+ let j = 0;
1358
+ while (j < pt.length) {
1359
+ const key = stripColon(pt[j++]);
1360
+ if (j < pt.length) {
1361
+ if (pt[j] === ":") {
1362
+ j++;
1363
+ }
1364
+ if (j < pt.length) {
1365
+ ref.parameters[key] = stripWrapping(pt[j++]);
1366
+ }
1367
+ }
1368
+ }
1369
+ } else if (cmd === "applicability") {
1370
+ ref.applicability = parseApplicability(unwrapBlock(t[i++]));
1371
+ } else {
1372
+ unwrapBlock(t[i++]);
1637
1373
  }
1638
1374
  }
1639
- out.push({ value: entry, label });
1640
- } else {
1641
- out.push(entry);
1642
1375
  }
1643
1376
  }
1644
- return out;
1377
+ return ref;
1645
1378
  }
1646
- function dumpValueEntry(e) {
1647
- if (typeof e === "string") {
1648
- return e;
1379
+ function dumpFormField(field, indent) {
1380
+ let out = "";
1381
+ if (field.subformRef && !field.name) {
1382
+ const sr = field.subformRef;
1383
+ out += indent + "subform_ref " + sr.subformId + " { ";
1384
+ const pkeys = Object.keys(sr.parameters);
1385
+ if (pkeys.length > 0) {
1386
+ out += "parameters { ";
1387
+ for (const k of pkeys) {
1388
+ out += k + ": " + sr.parameters[k] + " ";
1389
+ }
1390
+ out += "} ";
1391
+ }
1392
+ if (sr.applicability.length > 0) {
1393
+ out += "applicability { " + dumpApplicabilityEntries(sr.applicability) + "} ";
1394
+ }
1395
+ out += "}\n";
1396
+ return out;
1649
1397
  }
1650
- return e.value + ' { label "' + escapeString(e.label) + '" }';
1651
- }
1652
- function dumpBareSafe(v) {
1653
- return /[\s{}"]/.test(v) || v.endsWith(":") || v.startsWith("#") || v.startsWith("//") ? '"' + escapeString(v) + '"' : v;
1654
- }
1655
- function stripColon(x) {
1656
- return x.endsWith(":") ? x.slice(0, -1) : x;
1657
- }
1658
- function readBalanced(t, i) {
1659
- const first = t[i] ?? "";
1660
- if (!first.startsWith("[")) {
1661
- return { text: first, next: i + 1 };
1398
+ const inner = [];
1399
+ if (field.subformRef) {
1400
+ const sr = field.subformRef;
1401
+ let refLine = "subform_ref " + sr.subformId + " { ";
1402
+ const pkeys = Object.keys(sr.parameters);
1403
+ if (pkeys.length > 0) {
1404
+ refLine += "parameters { ";
1405
+ for (const k of pkeys) {
1406
+ refLine += k + ": " + sr.parameters[k] + " ";
1407
+ }
1408
+ refLine += "} ";
1409
+ }
1410
+ if (sr.applicability.length > 0) {
1411
+ refLine += "applicability { " + dumpApplicabilityEntries(sr.applicability) + "} ";
1412
+ }
1413
+ inner.push(refLine + "}");
1662
1414
  }
1663
- let text = first;
1664
- let j = i + 1;
1665
- while (!text.includes("]") && j < t.length) {
1666
- text += " " + t[j++];
1415
+ if (field.label) {
1416
+ inner.push('label "' + escapeString(field.label) + '"');
1667
1417
  }
1668
- return { text, next: j };
1669
- }
1670
- function subBlockTokens(block) {
1671
- return tokenizePackage(block).map((s) => s.replace(/^;+|;+$/g, "")).filter((s) => s.length > 0);
1672
- }
1673
- function readEntryTokens(value) {
1674
- if (value.startsWith("{")) {
1675
- return subBlockTokens(unwrapBlock(value)).flatMap((s) => s.split(",")).map((s) => stripWrapping(s.trim())).filter((s) => s.length > 0);
1418
+ if (field.definition) {
1419
+ inner.push('definition "' + escapeString(field.definition) + '"');
1676
1420
  }
1677
- const single = stripWrapping(value);
1678
- return single === "" ? [] : [single];
1679
- }
1680
- function readSource(block) {
1681
- const src = { doc: "", clause: "" };
1682
- const t = tokenize(block);
1683
- let i = 0;
1684
- while (i < t.length) {
1685
- const cmd = t[i++];
1686
- if (i >= t.length) {
1687
- break;
1688
- }
1689
- if (cmd === "doc") {
1690
- src.doc = stripWrapping(t[i++]);
1691
- } else if (cmd === "clause") {
1692
- src.clause = stripWrapping(t[i++]);
1693
- } else if (cmd === "fragment") {
1694
- src.fragment = stripWrapping(t[i++]);
1695
- } else {
1696
- unwrapBlock(t[i++]);
1697
- }
1421
+ if (field.description) {
1422
+ inner.push('description "' + escapeString(field.description) + '"');
1698
1423
  }
1699
- return src;
1700
- }
1701
- function readFieldHead(t, i) {
1702
- const name = t[i++];
1703
- if (name === void 0) {
1704
- return null;
1424
+ if (field.unit) {
1425
+ inner.push('unit "' + escapeString(field.unit) + '"');
1705
1426
  }
1706
- let type = "";
1707
- if (t[i] === ":") {
1708
- i++;
1709
- type = t[i++] ?? "";
1710
- if (t[i] && t[i].startsWith("[") && t[i].endsWith("]")) {
1711
- i++;
1712
- }
1427
+ if (field.symbol) {
1428
+ inner.push("symbol " + field.symbol);
1713
1429
  }
1714
- const blockToken = t[i++];
1715
- if (blockToken === void 0 || !blockToken.startsWith("{")) {
1716
- return null;
1430
+ if (field.verdict) {
1431
+ inner.push("verdict " + field.verdict);
1717
1432
  }
1718
- return { name, type, block: unwrapBlock(blockToken), next: i };
1719
- }
1720
- function parseFormField(name, block, type) {
1721
- const field = {
1722
- name,
1723
- type: type || "string",
1724
- typeDeclared: !!type,
1725
- label: "",
1726
- definition: "",
1727
- unit: "",
1728
- symbol: "",
1729
- verdict: "",
1730
- targets: [],
1731
- dimension: "",
1732
- enumRef: "",
1733
- pattern: "",
1734
- required: false,
1735
- requiredWhen: "",
1736
- refs: [],
1737
- measurementMethod: "",
1738
- calculationId: null,
1739
- calculationBindings: [],
1740
- derivation: "",
1741
- evaluation: null,
1742
- values: [],
1743
- trueLabel: "",
1744
- falseLabel: "",
1745
- enumValues: [],
1746
- defaultValue: "",
1747
- hasDefault: false,
1748
- referenceIds: [],
1749
- fieldReferences: [],
1750
- specificationReference: "",
1751
- applicability: [],
1752
- sourceDiscrepancy: null,
1753
- fields: [],
1754
- itemsType: "",
1755
- subformRef: null
1756
- };
1757
- if (!block || !block.trim()) {
1758
- return field;
1433
+ if (field.dimension) {
1434
+ inner.push("dimension " + field.dimension);
1759
1435
  }
1760
- const t = tokenize(block);
1761
- let i = 0;
1762
- while (i < t.length) {
1763
- const cmd = t[i++];
1764
- if (i >= t.length) {
1765
- break;
1766
- }
1767
- if (cmd === "label") {
1768
- field.label = stripWrapping(t[i++]);
1769
- } else if (cmd === "definition") {
1770
- field.definition = stripWrapping(t[i++]);
1771
- } else if (cmd === "description") {
1772
- field.description = stripWrapping(t[i++]);
1773
- } else if (cmd === "type") {
1774
- field.type = stripWrapping(t[i++]);
1775
- field.typeDeclared = true;
1776
- } else if (cmd === "unit") {
1777
- field.unit = stripWrapping(t[i++]);
1778
- } else if (cmd === "symbol") {
1779
- field.symbol = stripWrapping(t[i++]);
1780
- } else if (cmd === "verdict") {
1781
- field.verdict = stripWrapping(t[i++]);
1782
- } else if (cmd === "targets") {
1783
- field.targets = tokenizePackage(t[i++]).map(stripWrapping);
1784
- } else if (cmd === "dimension") {
1785
- field.dimension = stripWrapping(t[i++]);
1786
- } else if (cmd === "enum") {
1787
- field.enumRef = stripWrapping(t[i++]);
1788
- } else if (cmd === "pattern") {
1789
- field.pattern = stripWrapping(t[i++]);
1790
- } else if (cmd === "scope") {
1791
- field.scope = stripWrapping(t[i++]);
1792
- } else if (cmd === "examples") {
1793
- field.examples = stripWrapping(t[i++]);
1794
- } else if (cmd === "bind") {
1795
- field.bind = stripWrapping(t[i++]);
1796
- } else if (cmd === "required") {
1797
- field.required = stripWrapping(t[i++]) === "true";
1798
- } else if (cmd === "required_when") {
1799
- const read = readValueToken(t, i);
1800
- field.requiredWhen = stripWrapping(read.text);
1801
- i = read.next;
1802
- } else if (cmd === "measurement_method") {
1803
- field.measurementMethod = stripWrapping(t[i++]);
1804
- } else if (cmd === "calculation") {
1805
- const read = readValueToken(t, i);
1806
- field.calculationId = stripWrapping(read.text);
1807
- i = read.next;
1808
- } else if (cmd === "calculation_bindings") {
1809
- field.calculationBindings = parseCalculationBindings(unwrapBlock(t[i++]));
1810
- } else if (cmd === "derivation") {
1811
- field.derivation = stripWrapping(t[i++]);
1812
- } else if (cmd === "evaluation") {
1813
- field.evaluation = parseEvaluation(unwrapBlock(t[i++]));
1814
- } else if (cmd === "values") {
1815
- const read = readBalanced(t, i);
1816
- field.values = parseValueEntries(read.text);
1817
- i = read.next;
1818
- } else if (cmd === "default") {
1819
- field.defaultValue = stripWrapping(t[i++]);
1820
- field.hasDefault = true;
1821
- } else if (cmd === "true_label") {
1822
- field.trueLabel = stripWrapping(t[i++]);
1823
- } else if (cmd === "false_label") {
1824
- field.falseLabel = stripWrapping(t[i++]);
1825
- } else if (cmd === "enum_values") {
1826
- field.enumValues = parseValueEntries(t[i++]);
1827
- } else if (cmd === "min_items") {
1828
- const raw = stripWrapping(t[i++]);
1829
- const n = parseInt(raw, 10);
1830
- field.minItems = isNaN(n) ? raw : n;
1831
- } else if (cmd === "max_items") {
1832
- const raw = stripWrapping(t[i++]);
1833
- const n = parseInt(raw, 10);
1834
- field.maxItems = isNaN(n) ? raw : n;
1835
- } else if (cmd === "items") {
1836
- const iblock = unwrapBlock(t[i++]);
1837
- const it = tokenize(iblock);
1838
- const typeParts = [];
1839
- let k = 0;
1840
- while (k < it.length && it[k] !== "fields") {
1841
- if (it[k] === "unit" && k + 1 < it.length) {
1842
- field.itemsUnit = stripWrapping(it[k + 1]);
1843
- k += 2;
1844
- } else {
1845
- typeParts.push(it[k++]);
1846
- }
1847
- }
1848
- field.itemsType = typeParts.join(" ");
1849
- if (it[k] === "fields") {
1850
- k++;
1851
- if (k < it.length) {
1852
- field.fields = parseNestedFields(unwrapBlock(it[k]));
1853
- }
1436
+ if (field.enumRef) {
1437
+ inner.push("enum " + field.enumRef);
1438
+ }
1439
+ if (field.pattern) {
1440
+ inner.push('pattern "' + escapeString(field.pattern) + '"');
1441
+ }
1442
+ if (field.scope) {
1443
+ inner.push("scope " + field.scope);
1444
+ }
1445
+ if (field.examples) {
1446
+ inner.push('examples "' + escapeString(field.examples) + '"');
1447
+ }
1448
+ if (field.bind) {
1449
+ inner.push("bind " + dumpBareSafe(field.bind));
1450
+ }
1451
+ if (field.required) {
1452
+ inner.push("required true");
1453
+ }
1454
+ if (field.requiredWhen) {
1455
+ inner.push("required_when " + dumpBareSafe(field.requiredWhen));
1456
+ }
1457
+ if (field.measurementMethod) {
1458
+ inner.push("measurement_method " + field.measurementMethod);
1459
+ }
1460
+ if (field.calculationId) {
1461
+ inner.push("calculation " + dumpBareSafe(field.calculationId));
1462
+ }
1463
+ if (field.calculationBindings.length > 0) {
1464
+ inner.push(
1465
+ "calculation_bindings { " + field.calculationBindings.map((b) => b.inputName + ": " + b.pathExpr).join(" ") + "}"
1466
+ );
1467
+ }
1468
+ if (field.derivation) {
1469
+ inner.push('derivation "' + escapeString(field.derivation) + '"');
1470
+ }
1471
+ if (field.evaluation) {
1472
+ let ev = 'evaluation { rule "' + escapeString(field.evaluation.rule) + '"';
1473
+ if (field.evaluation.verdict) {
1474
+ ev += " verdict " + field.evaluation.verdict;
1475
+ }
1476
+ if (field.evaluation.op) {
1477
+ ev += " op " + field.evaluation.op;
1478
+ }
1479
+ if (field.evaluation.limit) {
1480
+ ev += ' limit "' + escapeString(field.evaluation.limit) + '"';
1481
+ }
1482
+ if (field.evaluation.condition) {
1483
+ ev += ' condition "' + escapeString(field.evaluation.condition) + '"';
1484
+ }
1485
+ if (field.evaluation.referenceId) {
1486
+ ev += " reference { " + field.evaluation.referenceId + " }";
1487
+ }
1488
+ if (field.evaluation.specificationReference) {
1489
+ ev += ' specification_reference "' + escapeString(field.evaluation.specificationReference) + '"';
1490
+ }
1491
+ if (field.evaluation.sourceDiscrepancy) {
1492
+ ev += " " + dumpSourceDiscrepancy(field.evaluation.sourceDiscrepancy, "");
1493
+ }
1494
+ inner.push(ev + " }");
1495
+ }
1496
+ if (field.values.length > 0) {
1497
+ inner.push("values { " + field.values.map(dumpValueEntry).join(" ") + " }");
1498
+ }
1499
+ if (field.hasDefault) {
1500
+ inner.push("default " + dumpBareSafe(field.defaultValue));
1501
+ }
1502
+ if (field.trueLabel) {
1503
+ inner.push('true_label "' + escapeString(field.trueLabel) + '"');
1504
+ }
1505
+ if (field.falseLabel) {
1506
+ inner.push('false_label "' + escapeString(field.falseLabel) + '"');
1507
+ }
1508
+ if (field.enumValues.length > 0) {
1509
+ inner.push(
1510
+ "enum_values { " + field.enumValues.map(dumpValueEntry).join(" ") + " }"
1511
+ );
1512
+ }
1513
+ if (field.itemsType) {
1514
+ let itemsLine = "items { " + field.itemsType;
1515
+ if (field.itemsUnit) {
1516
+ itemsLine += ' unit "' + escapeString(field.itemsUnit) + '"';
1517
+ }
1518
+ inner.push(itemsLine + " }");
1519
+ }
1520
+ if (field.minItems !== void 0 && field.minItems !== null) {
1521
+ inner.push("min_items " + dumpBareSafe(String(field.minItems)));
1522
+ }
1523
+ if (field.maxItems !== void 0 && field.maxItems !== null) {
1524
+ inner.push("max_items " + dumpBareSafe(String(field.maxItems)));
1525
+ }
1526
+ if (field.series) {
1527
+ inner.push(dumpSeriesDecl(field.series));
1528
+ }
1529
+ if (field.applicability.length > 0) {
1530
+ inner.push(
1531
+ "applicability { " + dumpApplicabilityEntries(field.applicability) + "}"
1532
+ );
1533
+ }
1534
+ if (field.targets.length > 0) {
1535
+ inner.push("targets { " + field.targets.join(" ") + " }");
1536
+ }
1537
+ if (field.sourceRefs && field.sourceRefs.length > 0) {
1538
+ for (const s of field.sourceRefs) {
1539
+ inner.push(dumpSourceRefAsRef(s, "", escapeString).trimEnd());
1540
+ }
1541
+ }
1542
+ if (field.fieldReferences.length > 0) {
1543
+ for (const r of field.fieldReferences) {
1544
+ inner.push(
1545
+ "ref " + roleToPredicateForDump(r.role) + ' "' + escapeString(r.urn) + '"'
1546
+ );
1547
+ }
1548
+ }
1549
+ if (field.refs && field.refs.length > 0) {
1550
+ for (const r of field.refs) {
1551
+ inner.push(
1552
+ "ref " + r.predicate + ' "' + escapeString(r.target) + '"' + (r.note ? ' { note "' + escapeString(r.note) + '" }' : "")
1553
+ );
1554
+ }
1555
+ }
1556
+ if (field.correspondences && field.correspondences.length > 0) {
1557
+ inner.push(
1558
+ dumpCorrespondences(
1559
+ field.correspondences,
1560
+ "",
1561
+ escapeString,
1562
+ dumpBareSafe
1563
+ ).trimEnd()
1564
+ );
1565
+ }
1566
+ if (field.specificationReference) {
1567
+ inner.push(
1568
+ 'specification_reference "' + escapeString(field.specificationReference) + '"'
1569
+ );
1570
+ }
1571
+ if (field.sourceDiscrepancy) {
1572
+ inner.push(dumpSourceDiscrepancy(field.sourceDiscrepancy, ""));
1573
+ }
1574
+ if (field.fields.length > 0) {
1575
+ inner.push(
1576
+ "fields {\n" + field.fields.map((f) => dumpFormField(f, indent + " ")).join("") + indent + " }"
1577
+ );
1578
+ }
1579
+ if (field.referenceIds.length > 0) {
1580
+ inner.push("reference { " + field.referenceIds.join(" ") + " }");
1581
+ }
1582
+ const typeSpec = field.type && (field.type !== "string" || field.typeDeclared) ? " : " + field.type : "";
1583
+ if (inner.length === 0) {
1584
+ return indent + "field " + field.name + typeSpec + " { }\n";
1585
+ }
1586
+ if (inner.every((s) => !s.includes("\n"))) {
1587
+ return indent + "field " + field.name + typeSpec + " { " + inner.join(" ") + " }\n";
1588
+ }
1589
+ return indent + "field " + field.name + typeSpec + " {\n" + inner.map((s) => indent + " " + s + "\n").join("") + indent + "}\n";
1590
+ }
1591
+ function dumpApplicabilityEntries(entries) {
1592
+ let out = "";
1593
+ for (const a of entries) {
1594
+ if (a.mapping) {
1595
+ out += a.dimension + ": { ";
1596
+ const pairs = [];
1597
+ for (const [k, v] of Object.entries(a.mapping)) {
1598
+ pairs.push(k + ": " + v);
1854
1599
  }
1855
- } else if (cmd === "series") {
1856
- field.series = parseSeriesDecl(unwrapBlock(t[i++]));
1857
- } else if (cmd === "fields") {
1858
- field.fields = parseNestedFields(unwrapBlock(t[i++]));
1859
- } else if (cmd === "subform_ref") {
1860
- const subformId = stripWrapping(t[i++]);
1861
- const refBlock = i < t.length ? unwrapBlock(t[i++]) : "";
1862
- field.subformRef = parseSubformRef(subformId, refBlock);
1863
- if (!field.type || field.type === "string") {
1864
- field.type = "array";
1600
+ out += pairs.join(", ") + " ";
1601
+ out += "} ";
1602
+ } else {
1603
+ out += a.dimension + ": [" + a.values.join(", ") + "] ";
1604
+ if (a.match) {
1605
+ out += "match " + a.match + " ";
1865
1606
  }
1866
- } else if (cmd === "reference") {
1867
- field.referenceIds = tokenizePackage(t[i++]).map(stripWrapping);
1868
- } else if (cmd === "references") {
1869
- field.fieldReferences = parseRoleReferences(unwrapBlock(t[i++]));
1870
- } else if (cmd === "ref") {
1871
- const r = parseRef(t, i, stripWrapping, unwrapBlock);
1872
- if (!foldRefIntoLegacy(field, r.ref)) {
1873
- field.refs.push(r.ref);
1607
+ }
1608
+ }
1609
+ return out;
1610
+ }
1611
+ function parseRoleReferences(block) {
1612
+ const out = [];
1613
+ const t = tokenize(block);
1614
+ let i = 0;
1615
+ while (i < t.length) {
1616
+ const role = stripColon(t[i++]);
1617
+ if (!role) {
1618
+ break;
1619
+ }
1620
+ if (i < t.length && t[i] === ":") {
1621
+ i++;
1622
+ }
1623
+ if (i < t.length && t[i].startsWith("{")) {
1624
+ const urns = tokenize(unwrapBlock(t[i++])).map(stripWrapping).filter((s) => s.length > 0);
1625
+ for (const urn of urns) {
1626
+ out.push({ urn, role });
1874
1627
  }
1875
- i = r.next;
1876
- } else if (cmd === "corresponds") {
1877
- const cc = parseCorresponds(t, i, stripWrapping);
1878
- (field.correspondences ??= []).push(cc.corr);
1879
- i = cc.next;
1880
- } else if (cmd === "specification_reference") {
1881
- field.specificationReference = stripWrapping(t[i++]);
1882
- } else if (cmd === "applicability") {
1883
- field.applicability = parseApplicability(unwrapBlock(t[i++]));
1884
- } else if (cmd === "source_discrepancy") {
1885
- field.sourceDiscrepancy = parseSourceDiscrepancy(unwrapBlock(t[i++]));
1886
- } else {
1887
- unwrapBlock(t[i++]);
1888
1628
  }
1889
1629
  }
1890
- return field;
1891
- }
1892
- function parseCalculationBindings(block) {
1893
- const out = [];
1894
- const t = tokenize(block);
1895
- let i = 0;
1896
- while (i < t.length) {
1897
- const key = stripColon(t[i++]);
1898
- if (i >= t.length) {
1899
- break;
1900
- }
1901
- if (t[i] === ":") {
1902
- i++;
1630
+ return out;
1631
+ }
1632
+ function roleToPredicateForDump(role) {
1633
+ if (role === "source") {
1634
+ return "derives-from";
1635
+ }
1636
+ if (role === "reference") {
1637
+ return "cites";
1638
+ }
1639
+ return role;
1640
+ }
1641
+
1642
+ // src/ser-des/config/approval.ts
1643
+ var parseApproval = function(id, data) {
1644
+ const result = {
1645
+ id,
1646
+ name: "",
1647
+ modality: "",
1648
+ actorRef: "",
1649
+ approverRef: "",
1650
+ recordRefs: [],
1651
+ actor: null,
1652
+ approver: null,
1653
+ records: [],
1654
+ ref: [],
1655
+ source: null,
1656
+ _relations: {
1657
+ actor: "",
1658
+ approver: "",
1659
+ records: [],
1660
+ ref: []
1661
+ }
1662
+ };
1663
+ forEachEntry(
1664
+ data,
1665
+ (keyword, value) => {
1666
+ if (keyword === "modality") {
1667
+ result.modality = value();
1668
+ } else if (keyword === "name") {
1669
+ result.name = unwrapped(value);
1670
+ } else if (keyword === "actor") {
1671
+ result._relations.actor = value();
1672
+ } else if (keyword === "approve_by") {
1673
+ result._relations.approver = value();
1674
+ } else if (keyword === "approval_record") {
1675
+ result._relations.records = tokenizePackage(value());
1676
+ } else if (keyword === "reference") {
1677
+ result._relations.ref = tokenizePackage(value());
1678
+ } else if (keyword === "source") {
1679
+ result.source = readSource(unwrapBlock(value()));
1680
+ } else {
1681
+ return false;
1682
+ }
1683
+ return true;
1684
+ },
1685
+ { construct: "approval", id }
1686
+ );
1687
+ return (ctx) => {
1688
+ ctx.approvals[id] = result;
1689
+ return ctx;
1690
+ };
1691
+ };
1692
+ var resolveApproval = function(ctx, unresolved) {
1693
+ const { _relations, ...rest } = unresolved;
1694
+ const p = {
1695
+ ...rest,
1696
+ // The raw reference ids survive resolution even when they name no
1697
+ // declared construct — the linter (C143) and the dumper read these.
1698
+ actorRef: _relations.actor,
1699
+ approverRef: _relations.approver,
1700
+ recordRefs: [..._relations.records],
1701
+ records: [],
1702
+ ref: []
1703
+ };
1704
+ if (_relations.actor !== "") {
1705
+ p.actor = resolveFromContext(ctx, "roles", _relations.actor) ?? null;
1706
+ }
1707
+ if (_relations.approver !== "") {
1708
+ p.approver = resolveFromContext(ctx, "roles", _relations.approver) ?? null;
1709
+ }
1710
+ for (const id of _relations.records) {
1711
+ const r = resolveFromContext(ctx, "regs", id);
1712
+ if (r !== void 0) {
1713
+ p.records.push(r);
1903
1714
  }
1904
- if (i < t.length) {
1905
- out.push({ inputName: key, pathExpr: stripWrapping(t[i++]) });
1715
+ }
1716
+ for (const id of _relations.ref) {
1717
+ const r = resolveFromContext(ctx, "references", id);
1718
+ if (r !== void 0) {
1719
+ p.ref.push(r);
1906
1720
  }
1907
1721
  }
1908
- return out;
1909
- }
1910
- function parseEvaluation(block) {
1911
- const rule = { rule: "", condition: "", referenceId: null };
1912
- const t = tokenize(block);
1913
- let i = 0;
1914
- while (i < t.length) {
1915
- const cmd = t[i++];
1916
- if (i >= t.length) {
1917
- break;
1722
+ return p;
1723
+ };
1724
+ var dumpApproval = function(approval) {
1725
+ let out = "approval " + approval.id + " {\n";
1726
+ out += ' name "' + escapeString(approval.name) + '"\n';
1727
+ if (approval.actorRef) {
1728
+ out += " actor " + approval.actorRef + "\n";
1729
+ }
1730
+ if (approval.modality !== "") {
1731
+ out += " modality " + approval.modality + "\n";
1732
+ }
1733
+ if (approval.approverRef) {
1734
+ out += " approve_by " + approval.approverRef + "\n";
1735
+ }
1736
+ if (approval.recordRefs.length > 0) {
1737
+ out += " approval_record {\n";
1738
+ for (const id of approval.recordRefs) {
1739
+ out += " " + id + "\n";
1918
1740
  }
1919
- if (cmd === "rule") {
1920
- rule.rule = stripWrapping(t[i++]);
1921
- } else if (cmd === "verdict") {
1922
- rule.verdict = stripWrapping(t[i++]);
1923
- } else if (cmd === "op") {
1924
- rule.op = stripWrapping(t[i++]);
1925
- } else if (cmd === "limit") {
1926
- rule.limit = stripWrapping(t[i++]);
1927
- } else if (cmd === "condition") {
1928
- rule.condition = stripWrapping(t[i++]);
1929
- } else if (cmd === "reference") {
1930
- const ids = tokenizePackage(t[i++]).map(stripWrapping);
1931
- rule.referenceId = ids[0] ?? null;
1932
- } else if (cmd === "specification_reference") {
1933
- rule.specificationReference = stripWrapping(t[i++]);
1934
- } else if (cmd === "source_discrepancy") {
1935
- rule.sourceDiscrepancy = parseSourceDiscrepancy(unwrapBlock(t[i++]));
1936
- } else {
1937
- unwrapBlock(t[i++]);
1741
+ out += " }\n";
1742
+ }
1743
+ if (approval.ref.length > 0) {
1744
+ out += " reference {\n";
1745
+ for (const r of approval.ref) {
1746
+ out += " " + r.id + "\n";
1938
1747
  }
1748
+ out += " }\n";
1939
1749
  }
1940
- return rule;
1941
- }
1942
- function parseNestedFields(block) {
1943
- const out = [];
1944
- const t = tokenize(block);
1945
- let i = 0;
1946
- while (i < t.length) {
1947
- const cmd = t[i++];
1948
- if (cmd !== "field") {
1949
- if (i < t.length) {
1950
- unwrapBlock(t[i - 1]);
1951
- }
1952
- continue;
1750
+ if (approval.source && (approval.source.doc || approval.source.clause)) {
1751
+ out += " source {\n";
1752
+ if (approval.source.doc) {
1753
+ out += ' doc "' + escapeString(approval.source.doc) + '"\n';
1953
1754
  }
1954
- const head = readFieldHead(t, i);
1955
- if (!head) {
1956
- break;
1755
+ if (approval.source.clause) {
1756
+ out += ' clause "' + escapeString(approval.source.clause) + '"\n';
1957
1757
  }
1958
- out.push(parseFormField(head.name, head.block, head.type || void 0));
1959
- i = head.next;
1758
+ out += " }\n";
1960
1759
  }
1760
+ out += "}\n";
1961
1761
  return out;
1962
- }
1963
- function parseApplicability(block) {
1964
- const entries = [];
1965
- const t = tokenize(block);
1966
- let i = 0;
1967
- while (i < t.length) {
1968
- const dimension = stripColon(t[i++]);
1969
- if (i >= t.length) {
1970
- break;
1971
- }
1972
- if (t[i] === ":") {
1973
- i++;
1974
- }
1975
- if (i < t.length) {
1976
- const read = readBalanced(t, i);
1977
- i = read.next;
1978
- const trimmed = read.text.trim();
1979
- let entry;
1980
- if (trimmed.startsWith("[")) {
1981
- const inner = trimmed.slice(1, trimmed.lastIndexOf("]"));
1982
- const values = inner.split(/[,\s]+/).filter((s) => s.length > 0);
1983
- entry = { dimension, values, mapping: null, match: null };
1984
- } else if (trimmed.startsWith("{")) {
1985
- const inner = trimmed.slice(1, -1);
1986
- const mapping = {};
1987
- for (const pair of inner.split(/[,\n]+/).map((s) => s.trim()).filter((s) => s)) {
1988
- const m = pair.match(/^(\w+)\s*:\s*(.+)$/);
1989
- if (m) {
1990
- mapping[m[1]] = m[2].trim();
1991
- }
1992
- }
1993
- entry = { dimension, values: [], mapping, match: null };
1762
+ };
1763
+
1764
+ // src/ser-des/config/data.ts
1765
+ var parseEnum = (id, data) => {
1766
+ const result = {
1767
+ id,
1768
+ values: []
1769
+ };
1770
+ forEachEntry(
1771
+ data,
1772
+ (_vid, value) => {
1773
+ result.values.push(parseEnumValue(_vid, value()));
1774
+ return true;
1775
+ },
1776
+ { construct: "enum", id }
1777
+ );
1778
+ return (ctx) => {
1779
+ ctx.enums[id] = result;
1780
+ return ctx;
1781
+ };
1782
+ };
1783
+ var parseEnumValue = (id, data) => {
1784
+ const ev = {
1785
+ id,
1786
+ value: ""
1787
+ };
1788
+ forEachEntry(
1789
+ data,
1790
+ (command, value) => {
1791
+ if (command === "definition") {
1792
+ ev.value = unwrapped(value);
1994
1793
  } else {
1995
- entry = {
1996
- dimension,
1997
- values: [stripWrapping(trimmed)],
1998
- mapping: null,
1999
- match: null
2000
- };
2001
- }
2002
- if (!entry.mapping && t[i] === "match") {
2003
- i++;
2004
- const mode = stripWrapping(t[i++] ?? "");
2005
- if (mode !== "any" && mode !== "all" && mode !== "exact") {
2006
- throw new Error(
2007
- `Parsing error: applicability: Unknown match ${mode} (valid: any, all, exact)`
2008
- );
2009
- }
2010
- entry.match = mode;
1794
+ return false;
2011
1795
  }
2012
- entries.push(entry);
1796
+ return true;
1797
+ },
1798
+ { construct: "enum value", id }
1799
+ );
1800
+ return ev;
1801
+ };
1802
+ var parseRegistry = function(id, data) {
1803
+ const result = {
1804
+ id,
1805
+ title: "",
1806
+ data: null,
1807
+ _relations: {
1808
+ data: ""
2013
1809
  }
2014
- }
2015
- return entries;
2016
- }
2017
- function parseSubformRef(subformId, block) {
2018
- const ref = {
2019
- subformId: stripWrapping(subformId),
2020
- parameters: {},
2021
- applicability: []
2022
1810
  };
2023
- if (block && block.trim()) {
2024
- const t = tokenize(block);
2025
- let i = 0;
2026
- while (i < t.length) {
2027
- const cmd = t[i++];
2028
- if (i < t.length) {
2029
- if (cmd === "parameters") {
2030
- const pblock = unwrapBlock(t[i++]);
2031
- const pt = tokenize(pblock);
2032
- let j = 0;
2033
- while (j < pt.length) {
2034
- const key = stripColon(pt[j++]);
2035
- if (j < pt.length) {
2036
- if (pt[j] === ":") {
2037
- j++;
2038
- }
2039
- if (j < pt.length) {
2040
- ref.parameters[key] = stripWrapping(pt[j++]);
2041
- }
1811
+ forEachEntry(
1812
+ data,
1813
+ (command, value) => {
1814
+ if (command === "title") {
1815
+ result.title = unwrapped(value);
1816
+ } else if (command === "data_class") {
1817
+ result._relations.data = value();
1818
+ } else {
1819
+ return false;
1820
+ }
1821
+ return true;
1822
+ },
1823
+ { construct: "registry", id }
1824
+ );
1825
+ return (ctx) => {
1826
+ ctx.regs[id] = result;
1827
+ return ctx;
1828
+ };
1829
+ };
1830
+ var parseDataClass = function(id, data) {
1831
+ const result = {
1832
+ id,
1833
+ attributes: []
1834
+ };
1835
+ forEachAttribute(
1836
+ data,
1837
+ (basic, details) => {
1838
+ if (basic.startsWith("ref ")) {
1839
+ const m = basic.match(/^ref\s+(\S+)\s+"([^"]*)"$/);
1840
+ if (m) {
1841
+ const ref = { predicate: m[1], target: m[2] };
1842
+ if (details) {
1843
+ const noteMatch = /note\s+"([^"]*)"/.exec(details) ?? /note\s+(\S+)/.exec(details);
1844
+ if (noteMatch) {
1845
+ ref.note = noteMatch[1];
2042
1846
  }
2043
1847
  }
2044
- } else if (cmd === "applicability") {
2045
- ref.applicability = parseApplicability(unwrapBlock(t[i++]));
2046
- } else {
2047
- unwrapBlock(t[i++]);
1848
+ result.ref ??= [];
1849
+ result.ref.push(ref);
1850
+ return;
2048
1851
  }
2049
1852
  }
2050
- }
2051
- }
2052
- return ref;
2053
- }
2054
- function dumpFormField(field, indent) {
2055
- let out = "";
2056
- if (field.subformRef && !field.name) {
2057
- const sr = field.subformRef;
2058
- out += indent + "subform_ref " + sr.subformId + " { ";
2059
- const pkeys = Object.keys(sr.parameters);
2060
- if (pkeys.length > 0) {
2061
- out += "parameters { ";
2062
- for (const k of pkeys) {
2063
- out += k + ": " + sr.parameters[k] + " ";
1853
+ const head = basic.trim();
1854
+ if (head === "store") {
1855
+ result.store = details.trim();
1856
+ return;
2064
1857
  }
2065
- out += "} ";
2066
- }
2067
- if (sr.applicability.length > 0) {
2068
- out += "applicability { " + dumpApplicabilityEntries(sr.applicability) + "} ";
1858
+ if (head === "description") {
1859
+ result.description = stripWrapping(details.trim());
1860
+ return;
1861
+ }
1862
+ if (head === "indexes") {
1863
+ result.indexes = details.split(/\s+/).filter((x) => x.length > 0);
1864
+ return;
1865
+ }
1866
+ if (head === "helper") {
1867
+ result.helper = details.trim() === "true";
1868
+ return;
1869
+ }
1870
+ if (head === "extends") {
1871
+ result.extends = details.trim();
1872
+ return;
1873
+ }
1874
+ result.attributes.push(parseDataAttribute(head, details));
1875
+ },
1876
+ { construct: "class", id }
1877
+ );
1878
+ return (ctx) => {
1879
+ ctx.dataclasses[id] = result;
1880
+ return ctx;
1881
+ };
1882
+ };
1883
+ var parseDataAttribute = (basic, details) => {
1884
+ const result = {
1885
+ id: "",
1886
+ type: "",
1887
+ modality: "",
1888
+ cardinality: "",
1889
+ definition: "",
1890
+ ref: [],
1891
+ satisfy: [],
1892
+ _relations: {
1893
+ ref: []
2069
1894
  }
2070
- out += "}\n";
2071
- return out;
1895
+ };
1896
+ const cardMatch = basic.match(/^(.*?)\s*\[([\d*][^\]]*)\]\s*$/);
1897
+ if (cardMatch) {
1898
+ result.cardinality = cardMatch[2].trim();
1899
+ basic = cardMatch[1];
2072
1900
  }
2073
- const inner = [];
2074
- if (field.subformRef) {
2075
- const sr = field.subformRef;
2076
- let refLine = "subform_ref " + sr.subformId + " { ";
2077
- const pkeys = Object.keys(sr.parameters);
2078
- if (pkeys.length > 0) {
2079
- refLine += "parameters { ";
2080
- for (const k of pkeys) {
2081
- refLine += k + ": " + sr.parameters[k] + " ";
1901
+ const colonIndex = basic.indexOf(":");
1902
+ if (colonIndex !== -1) {
1903
+ result.type = basic.substr(colonIndex + 1, basic.length - colonIndex - 1).trim();
1904
+ basic = basic.substr(0, colonIndex);
1905
+ }
1906
+ result.id = basic.trim();
1907
+ forEachEntry(
1908
+ details,
1909
+ (keyword, value) => {
1910
+ if (keyword === "modality") {
1911
+ result.modality = value();
1912
+ } else if (keyword === "definition") {
1913
+ result.definition = unwrapped(value);
1914
+ } else if (keyword === "reference") {
1915
+ result._relations.ref = tokenizePackage(value());
1916
+ } else if (keyword === "satisfy") {
1917
+ result.satisfy = tokenizePackage(value());
1918
+ } else if (keyword === "on_delete") {
1919
+ result.onDelete = value();
1920
+ } else if (keyword === "deprecated") {
1921
+ result.deprecated = value() === "true";
1922
+ } else if (keyword === "enum_values") {
1923
+ result.enumValues = tokenizePackage(value());
1924
+ } else if (keyword === "required") {
1925
+ result.required = value() === "true";
1926
+ } else if (keyword === "unit") {
1927
+ result.unit = unwrapped(value);
1928
+ } else if (keyword === "default") {
1929
+ result.defaultValue = unwrapped(value);
1930
+ } else {
1931
+ return false;
1932
+ }
1933
+ return true;
1934
+ },
1935
+ { construct: "data attribute", id: result.id }
1936
+ );
1937
+ return result;
1938
+ };
1939
+ var resolveDataClass = function(ctx, unresolved) {
1940
+ const attributes = unresolved.attributes.map((attr) => {
1941
+ const resolved = { ...attr, ref: [] };
1942
+ for (const id of attr._relations.ref) {
1943
+ const r = resolveFromContext(ctx, "references", id);
1944
+ if (r !== void 0) {
1945
+ resolved.ref.push(r);
2082
1946
  }
2083
- refLine += "} ";
2084
1947
  }
2085
- if (sr.applicability.length > 0) {
2086
- refLine += "applicability { " + dumpApplicabilityEntries(sr.applicability) + "} ";
1948
+ return resolved;
1949
+ });
1950
+ return {
1951
+ id: unresolved.id,
1952
+ attributes,
1953
+ ...unresolved.store !== void 0 ? { store: unresolved.store } : {},
1954
+ ...unresolved.indexes !== void 0 ? { indexes: unresolved.indexes } : {},
1955
+ ...unresolved.helper !== void 0 ? { helper: unresolved.helper } : {},
1956
+ ...unresolved.extends !== void 0 ? { extends: unresolved.extends } : {},
1957
+ ...unresolved.description !== void 0 ? { description: unresolved.description } : {},
1958
+ ...unresolved.ref !== void 0 ? { ref: unresolved.ref } : {}
1959
+ };
1960
+ };
1961
+ var resolveRegistry = function(ctx, unresolved) {
1962
+ const { _relations, ...rest } = unresolved;
1963
+ const p = { ...rest, data: null };
1964
+ if (_relations.data !== "") {
1965
+ const dc = resolveFromContext(
1966
+ ctx,
1967
+ "dataclasses",
1968
+ _relations.data
1969
+ );
1970
+ if (dc !== void 0) {
1971
+ p.data = dc;
2087
1972
  }
2088
- inner.push(refLine + "}");
2089
- }
2090
- if (field.label) {
2091
- inner.push('label "' + escapeString(field.label) + '"');
2092
- }
2093
- if (field.definition) {
2094
- inner.push('definition "' + escapeString(field.definition) + '"');
2095
- }
2096
- if (field.description) {
2097
- inner.push('description "' + escapeString(field.description) + '"');
2098
- }
2099
- if (field.unit) {
2100
- inner.push('unit "' + escapeString(field.unit) + '"');
2101
1973
  }
2102
- if (field.symbol) {
2103
- inner.push("symbol " + field.symbol);
2104
- }
2105
- if (field.verdict) {
2106
- inner.push("verdict " + field.verdict);
2107
- }
2108
- if (field.dimension) {
2109
- inner.push("dimension " + field.dimension);
2110
- }
2111
- if (field.enumRef) {
2112
- inner.push("enum " + field.enumRef);
2113
- }
2114
- if (field.pattern) {
2115
- inner.push('pattern "' + escapeString(field.pattern) + '"');
2116
- }
2117
- if (field.scope) {
2118
- inner.push("scope " + field.scope);
1974
+ return p;
1975
+ };
1976
+ var dumpDataClass = function(dataclass) {
1977
+ let out = "class " + dataclass.id + " {\n";
1978
+ if (dataclass.store) {
1979
+ out += " store { " + dataclass.store + " }\n";
2119
1980
  }
2120
- if (field.examples) {
2121
- inner.push('examples "' + escapeString(field.examples) + '"');
1981
+ if (dataclass.description) {
1982
+ out += ' description { "' + escapeString(dataclass.description) + '" }\n';
2122
1983
  }
2123
- if (field.bind) {
2124
- inner.push("bind " + dumpBareSafe(field.bind));
1984
+ if (dataclass.indexes && dataclass.indexes.length > 0) {
1985
+ out += " indexes { " + dataclass.indexes.join(" ") + " }\n";
2125
1986
  }
2126
- if (field.required) {
2127
- inner.push("required true");
1987
+ if (dataclass.helper !== void 0) {
1988
+ out += " helper { " + dataclass.helper + " }\n";
2128
1989
  }
2129
- if (field.requiredWhen) {
2130
- inner.push("required_when " + dumpBareSafe(field.requiredWhen));
1990
+ if (dataclass.extends) {
1991
+ out += " extends { " + dataclass.extends + " }\n";
2131
1992
  }
2132
- if (field.measurementMethod) {
2133
- inner.push("measurement_method " + field.measurementMethod);
1993
+ if (dataclass.ref && dataclass.ref.length > 0) {
1994
+ for (const r of dataclass.ref) {
1995
+ out += " ref " + r.predicate + ' "' + escapeString(r.target) + '"';
1996
+ if (r.note) {
1997
+ out += ' { note "' + escapeString(r.note) + '" }';
1998
+ }
1999
+ out += "\n";
2000
+ }
2134
2001
  }
2135
- if (field.calculationId) {
2136
- inner.push("calculation " + dumpBareSafe(field.calculationId));
2002
+ for (const a of dataclass.attributes) {
2003
+ out += toDataAttributeModel(a);
2137
2004
  }
2138
- if (field.calculationBindings.length > 0) {
2139
- inner.push(
2140
- "calculation_bindings { " + field.calculationBindings.map((b) => b.inputName + ": " + b.pathExpr).join(" ") + "}"
2141
- );
2005
+ out += "}\n";
2006
+ return out;
2007
+ };
2008
+ var toDataAttributeModel = (attribute) => {
2009
+ let out = " " + attribute.id;
2010
+ if (attribute.type !== "") {
2011
+ out += ": " + attribute.type;
2142
2012
  }
2143
- if (field.derivation) {
2144
- inner.push('derivation "' + escapeString(field.derivation) + '"');
2013
+ if (attribute.cardinality !== "") {
2014
+ out += "[" + attribute.cardinality + "]";
2145
2015
  }
2146
- if (field.evaluation) {
2147
- let ev = 'evaluation { rule "' + escapeString(field.evaluation.rule) + '"';
2148
- if (field.evaluation.verdict) {
2149
- ev += " verdict " + field.evaluation.verdict;
2150
- }
2151
- if (field.evaluation.op) {
2152
- ev += " op " + field.evaluation.op;
2153
- }
2154
- if (field.evaluation.limit) {
2155
- ev += ' limit "' + escapeString(field.evaluation.limit) + '"';
2156
- }
2157
- if (field.evaluation.condition) {
2158
- ev += ' condition "' + escapeString(field.evaluation.condition) + '"';
2159
- }
2160
- if (field.evaluation.referenceId) {
2161
- ev += " reference { " + field.evaluation.referenceId + " }";
2162
- }
2163
- if (field.evaluation.specificationReference) {
2164
- ev += ' specification_reference "' + escapeString(field.evaluation.specificationReference) + '"';
2165
- }
2166
- if (field.evaluation.sourceDiscrepancy) {
2167
- ev += " " + dumpSourceDiscrepancy(field.evaluation.sourceDiscrepancy, "");
2168
- }
2169
- inner.push(ev + " }");
2016
+ out += " {\n";
2017
+ out += ' definition "' + escapeString(attribute.definition) + '"\n';
2018
+ if (attribute.modality !== "") {
2019
+ out += " modality " + attribute.modality + "\n";
2170
2020
  }
2171
- if (field.values.length > 0) {
2172
- inner.push("values { " + field.values.map(dumpValueEntry).join(" ") + " }");
2021
+ if (attribute.onDelete) {
2022
+ out += " on_delete " + attribute.onDelete + "\n";
2173
2023
  }
2174
- if (field.hasDefault) {
2175
- inner.push("default " + dumpBareSafe(field.defaultValue));
2024
+ if (attribute.deprecated) {
2025
+ out += " deprecated true\n";
2176
2026
  }
2177
- if (field.trueLabel) {
2178
- inner.push('true_label "' + escapeString(field.trueLabel) + '"');
2027
+ if (attribute.enumValues && attribute.enumValues.length > 0) {
2028
+ out += " enum_values { " + attribute.enumValues.join(" ") + " }\n";
2179
2029
  }
2180
- if (field.falseLabel) {
2181
- inner.push('false_label "' + escapeString(field.falseLabel) + '"');
2030
+ if (attribute.required !== void 0) {
2031
+ out += " required " + (attribute.required ? "true" : "false") + "\n";
2182
2032
  }
2183
- if (field.enumValues.length > 0) {
2184
- inner.push(
2185
- "enum_values { " + field.enumValues.map(dumpValueEntry).join(" ") + " }"
2186
- );
2033
+ if (attribute.unit) {
2034
+ out += ' unit "' + escapeString(attribute.unit) + '"\n';
2187
2035
  }
2188
- if (field.itemsType) {
2189
- let itemsLine = "items { " + field.itemsType;
2190
- if (field.itemsUnit) {
2191
- itemsLine += ' unit "' + escapeString(field.itemsUnit) + '"';
2036
+ if (attribute.defaultValue !== void 0) {
2037
+ out += ' default "' + escapeString(attribute.defaultValue) + '"\n';
2038
+ }
2039
+ if (attribute.satisfy.length > 0) {
2040
+ out += " satisfy {\n";
2041
+ for (const s of attribute.satisfy) {
2042
+ out += " " + s + "\n";
2192
2043
  }
2193
- inner.push(itemsLine + " }");
2044
+ out += " }\n";
2194
2045
  }
2195
- if (field.minItems !== void 0 && field.minItems !== null) {
2196
- inner.push("min_items " + dumpBareSafe(String(field.minItems)));
2046
+ if (attribute.ref.length > 0) {
2047
+ out += " reference {\n";
2048
+ for (const r of attribute.ref) {
2049
+ out += " " + r.id + "\n";
2050
+ }
2051
+ out += " }\n";
2197
2052
  }
2198
- if (field.maxItems !== void 0 && field.maxItems !== null) {
2199
- inner.push("max_items " + dumpBareSafe(String(field.maxItems)));
2053
+ out += " }\n";
2054
+ return out;
2055
+ };
2056
+ var dumpEnumValue = (ev) => {
2057
+ let out = " " + ev.id + " {\n";
2058
+ out += ' definition "' + escapeString(ev.value) + '"\n';
2059
+ out += " }\n";
2060
+ return out;
2061
+ };
2062
+ var dumpEnum = function(en) {
2063
+ let out = "enum " + en.id + " {\n";
2064
+ for (const v of en.values) {
2065
+ out += dumpEnumValue(v);
2200
2066
  }
2201
- if (field.series) {
2202
- inner.push(dumpSeriesDecl(field.series));
2067
+ out += "}\n";
2068
+ return out;
2069
+ };
2070
+ var dumpRegistry = function(reg) {
2071
+ let out = "data_registry " + reg.id + " {\n";
2072
+ out += ' title "' + escapeString(reg.title) + '"\n';
2073
+ if (reg.data !== null) {
2074
+ out += " data_class " + reg.data.id + "\n";
2203
2075
  }
2204
- if (field.applicability.length > 0) {
2205
- inner.push(
2206
- "applicability { " + dumpApplicabilityEntries(field.applicability) + "}"
2207
- );
2076
+ out += "}\n";
2077
+ return out;
2078
+ };
2079
+ var parseVariable = function(id, data) {
2080
+ const result = {
2081
+ id,
2082
+ type: "",
2083
+ definition: "",
2084
+ description: ""
2085
+ };
2086
+ forEachEntry(
2087
+ data,
2088
+ (keyword, value) => {
2089
+ if (keyword === "type") {
2090
+ result.type = value();
2091
+ } else if (keyword === "definition") {
2092
+ result.definition = unwrapped(value);
2093
+ } else if (keyword === "description") {
2094
+ result.description = unwrapped(value);
2095
+ } else {
2096
+ return false;
2097
+ }
2098
+ return true;
2099
+ },
2100
+ { construct: "variable", id }
2101
+ );
2102
+ return (ctx) => {
2103
+ ctx.variables[id] = result;
2104
+ return ctx;
2105
+ };
2106
+ };
2107
+ var dumpVariable = function(v) {
2108
+ let out = "variable " + v.id + " {\n";
2109
+ if (v.type !== "") {
2110
+ out += " type " + v.type + "\n";
2208
2111
  }
2209
- if (field.targets.length > 0) {
2210
- inner.push("targets { " + field.targets.join(" ") + " }");
2112
+ if (v.definition !== "") {
2113
+ out += ' definition "' + escapeString(v.definition) + '"\n';
2211
2114
  }
2212
- if (field.sourceRefs && field.sourceRefs.length > 0) {
2213
- for (const s of field.sourceRefs) {
2214
- inner.push(dumpSourceRefAsRef(s, "", escapeString).trimEnd());
2215
- }
2115
+ if (v.description !== "") {
2116
+ out += ' description "' + escapeString(v.description) + '"\n';
2216
2117
  }
2217
- if (field.fieldReferences.length > 0) {
2218
- for (const r of field.fieldReferences) {
2219
- inner.push(
2220
- "ref " + roleToPredicateForDump(r.role) + ' "' + escapeString(r.urn) + '"'
2118
+ out += "}\n";
2119
+ return out;
2120
+ };
2121
+
2122
+ // src/ser-des/config/event.ts
2123
+ var parseEndEvent = function(id, data) {
2124
+ const result = {
2125
+ id,
2126
+ eventType: "end"
2127
+ };
2128
+ if (data !== "") {
2129
+ const t = tokenizePackage(data);
2130
+ if (t.length > 0) {
2131
+ throw new Error(
2132
+ `Parsing error: end_event. ID ${id}: Expecting empty body`
2221
2133
  );
2222
2134
  }
2223
2135
  }
2224
- if (field.refs && field.refs.length > 0) {
2225
- for (const r of field.refs) {
2226
- inner.push(
2227
- "ref " + r.predicate + ' "' + escapeString(r.target) + '"' + (r.note ? ' { note "' + escapeString(r.note) + '" }' : "")
2136
+ return (ctx) => {
2137
+ ctx.events[id] = result;
2138
+ return ctx;
2139
+ };
2140
+ };
2141
+ var parseSignalCatchEvent = function(id, data) {
2142
+ const result = {
2143
+ id,
2144
+ eventType: "signalcatch",
2145
+ signal: ""
2146
+ };
2147
+ if (data !== "") {
2148
+ const t = tokenizePackage(data);
2149
+ let i = 0;
2150
+ while (i < t.length) {
2151
+ const command = t[i++];
2152
+ if (i < t.length) {
2153
+ if (command === "catch") {
2154
+ result.signal = unwrapBlock(t[i++]);
2155
+ } else {
2156
+ i++;
2157
+ }
2158
+ } else {
2159
+ throw new Error(
2160
+ `Parsing error: Signal Catch Event. ID ${id}: Expecting value for ${command}`
2161
+ );
2162
+ }
2163
+ }
2164
+ }
2165
+ return (ctx) => {
2166
+ ctx.events[id] = result;
2167
+ return ctx;
2168
+ };
2169
+ };
2170
+ var parseStartEvent = function(id, data) {
2171
+ const result = {
2172
+ id,
2173
+ eventType: "start"
2174
+ };
2175
+ if (data !== "") {
2176
+ const t = tokenizePackage(data);
2177
+ if (t.length > 0) {
2178
+ throw new Error(
2179
+ `Parsing error: end_event. ID ${id}: Expecting empty body`
2228
2180
  );
2229
2181
  }
2230
2182
  }
2231
- if (field.correspondences && field.correspondences.length > 0) {
2232
- inner.push(
2233
- dumpCorrespondences(
2234
- field.correspondences,
2235
- "",
2236
- escapeString,
2237
- dumpBareSafe
2238
- ).trimEnd()
2239
- );
2183
+ return (ctx) => {
2184
+ ctx.events[id] = result;
2185
+ return ctx;
2186
+ };
2187
+ };
2188
+ var parseTimerEvent = function(id, data) {
2189
+ const result = {
2190
+ id,
2191
+ eventType: "timer",
2192
+ type: "",
2193
+ para: ""
2194
+ };
2195
+ if (data !== "") {
2196
+ const t = tokenizePackage(data);
2197
+ let i = 0;
2198
+ while (i < t.length) {
2199
+ const command = t[i++];
2200
+ if (i < t.length) {
2201
+ if (command === "type") {
2202
+ result.type = t[i++];
2203
+ } else if (command === "para") {
2204
+ result.para = unwrapBlock(t[i++]);
2205
+ } else {
2206
+ i++;
2207
+ }
2208
+ } else {
2209
+ throw new Error(
2210
+ `Parsing error: Timer Event. ID ${id}: Expecting value for ${command}`
2211
+ );
2212
+ }
2213
+ }
2240
2214
  }
2241
- if (field.specificationReference) {
2242
- inner.push(
2243
- 'specification_reference "' + escapeString(field.specificationReference) + '"'
2244
- );
2215
+ return (ctx) => {
2216
+ ctx.events[id] = result;
2217
+ return ctx;
2218
+ };
2219
+ };
2220
+ var dumpEvent = function(event) {
2221
+ if (event.eventType === "start") {
2222
+ return dumpStartEvent(event);
2245
2223
  }
2246
- if (field.sourceDiscrepancy) {
2247
- inner.push(dumpSourceDiscrepancy(field.sourceDiscrepancy, ""));
2224
+ if (event.eventType === "end") {
2225
+ return dumpEndEvent(event);
2248
2226
  }
2249
- if (field.fields.length > 0) {
2250
- inner.push(
2251
- "fields {\n" + field.fields.map((f) => dumpFormField(f, indent + " ")).join("") + indent + " }"
2252
- );
2227
+ if (event.eventType === "signalcatch") {
2228
+ return dumpSignalCatchEvent(event);
2253
2229
  }
2254
- if (field.referenceIds.length > 0) {
2255
- inner.push("reference { " + field.referenceIds.join(" ") + " }");
2230
+ if (event.eventType === "timer") {
2231
+ return dumpTimerEvent(event);
2232
+ }
2233
+ return "";
2234
+ };
2235
+ function dumpEndEvent(end) {
2236
+ return "end_event " + end.id + " {\n}\n";
2237
+ }
2238
+ function dumpSignalCatchEvent(sc) {
2239
+ let out = "signal_catch_event " + sc.id + " {\n";
2240
+ if (sc.signal !== "") {
2241
+ out += ' catch "' + escapeString(sc.signal) + '"\n';
2256
2242
  }
2257
- const typeSpec = field.type && (field.type !== "string" || field.typeDeclared) ? " : " + field.type : "";
2258
- if (inner.length === 0) {
2259
- return indent + "field " + field.name + typeSpec + " { }\n";
2243
+ out += "}\n";
2244
+ return out;
2245
+ }
2246
+ function dumpStartEvent(s) {
2247
+ return "start_event " + s.id + " {\n}\n";
2248
+ }
2249
+ function dumpTimerEvent(te) {
2250
+ let out = "timer_event " + te.id + " {\n";
2251
+ if (te.type !== "") {
2252
+ out += " type " + te.type + "\n";
2260
2253
  }
2261
- if (inner.every((s) => !s.includes("\n"))) {
2262
- return indent + "field " + field.name + typeSpec + " { " + inner.join(" ") + " }\n";
2254
+ if (te.para !== "") {
2255
+ out += ' para "' + escapeString(te.para) + '"\n';
2263
2256
  }
2264
- return indent + "field " + field.name + typeSpec + " {\n" + inner.map((s) => indent + " " + s + "\n").join("") + indent + "}\n";
2257
+ out += "}\n";
2258
+ return out;
2265
2259
  }
2266
- function dumpApplicabilityEntries(entries) {
2267
- let out = "";
2268
- for (const a of entries) {
2269
- if (a.mapping) {
2270
- out += a.dimension + ": { ";
2271
- const pairs = [];
2272
- for (const [k, v] of Object.entries(a.mapping)) {
2273
- pairs.push(k + ": " + v);
2274
- }
2275
- out += pairs.join(", ") + " ";
2276
- out += "} ";
2277
- } else {
2278
- out += a.dimension + ": [" + a.values.join(", ") + "] ";
2279
- if (a.match) {
2280
- out += "match " + a.match + " ";
2260
+
2261
+ // src/ser-des/config/gateway.ts
2262
+ var parseExclusiveGate = function(id, data) {
2263
+ const gateway = {
2264
+ id,
2265
+ gatewayType: "exclusive_gateway",
2266
+ label: "",
2267
+ edges: []
2268
+ };
2269
+ forEachEntry(
2270
+ data,
2271
+ (command, value) => {
2272
+ if (command === "label") {
2273
+ gateway.label = unwrapped(value);
2274
+ } else if (command === "edge") {
2275
+ const edge = {
2276
+ target: stripWrapping(value()),
2277
+ condition: "",
2278
+ label: ""
2279
+ };
2280
+ const et = tokenize(unwrapBlock(value()));
2281
+ for (let j = 0; j + 1 < et.length; j += 2) {
2282
+ if (et[j] === "condition") {
2283
+ edge.condition = stripWrapping(et[j + 1]);
2284
+ } else if (et[j] === "label") {
2285
+ edge.label = stripWrapping(et[j + 1]);
2286
+ }
2287
+ }
2288
+ gateway.edges.push(edge);
2289
+ } else {
2290
+ return false;
2281
2291
  }
2282
- }
2292
+ return true;
2293
+ },
2294
+ { construct: "Exclusive gateway", id }
2295
+ );
2296
+ return (ctx) => {
2297
+ ctx.gateways[id] = gateway;
2298
+ return ctx;
2299
+ };
2300
+ };
2301
+ var dumpGateway = function(gate) {
2302
+ if (gate.gatewayType === "exclusive_gateway") {
2303
+ return dumpEGate(gate);
2283
2304
  }
2284
- return out;
2285
- }
2286
- function parseRoleReferences(block) {
2287
- const out = [];
2288
- const t = tokenize(block);
2289
- let i = 0;
2290
- while (i < t.length) {
2291
- const role = stripColon(t[i++]);
2292
- if (!role) {
2293
- break;
2294
- }
2295
- if (i < t.length && t[i] === ":") {
2296
- i++;
2305
+ return "";
2306
+ };
2307
+ function dumpEGate(egate) {
2308
+ let out = "exclusive_gateway " + egate.id + " {\n";
2309
+ if (egate.label !== "") {
2310
+ out += ' label "' + escapeString(egate.label) + '"\n';
2311
+ }
2312
+ for (const e of egate.edges ?? []) {
2313
+ out += " edge " + dumpBareSafe(e.target) + " {";
2314
+ if (e.condition === "default") {
2315
+ out += " condition default";
2316
+ } else if (e.condition !== "") {
2317
+ out += ' condition "' + escapeString(e.condition) + '"';
2297
2318
  }
2298
- if (i < t.length && t[i].startsWith("{")) {
2299
- const urns = tokenize(unwrapBlock(t[i++])).map(stripWrapping).filter((s) => s.length > 0);
2300
- for (const urn of urns) {
2301
- out.push({ urn, role });
2302
- }
2319
+ if (e.label !== "") {
2320
+ out += ' label "' + escapeString(e.label) + '"';
2303
2321
  }
2322
+ out += " }\n";
2304
2323
  }
2324
+ out += "}\n";
2305
2325
  return out;
2306
2326
  }
2307
- function roleToPredicateForDump(role) {
2308
- if (role === "source") {
2309
- return "derives-from";
2310
- }
2311
- if (role === "reference") {
2312
- return "cites";
2327
+
2328
+ // src/ser-des/config/metadata.ts
2329
+ var parseMetadata = function(token) {
2330
+ const metadata = {
2331
+ schema: "",
2332
+ author: "",
2333
+ title: "",
2334
+ edition: "",
2335
+ namespace: "",
2336
+ shortname: ""
2337
+ };
2338
+ if (token !== "") {
2339
+ const t = tokenizePackage(token);
2340
+ let i = 0;
2341
+ while (i < t.length) {
2342
+ const keyword = t[i++];
2343
+ if (i < t.length) {
2344
+ if (keyword === "title") {
2345
+ metadata.title = stripWrapping(t[i++]);
2346
+ } else if (keyword === "schema") {
2347
+ metadata.schema = stripWrapping(t[i++]);
2348
+ } else if (keyword === "edition") {
2349
+ metadata.edition = stripWrapping(t[i++]);
2350
+ } else if (keyword === "author") {
2351
+ metadata.author = stripWrapping(t[i++]);
2352
+ } else if (keyword === "namespace") {
2353
+ metadata.namespace = stripWrapping(t[i++]);
2354
+ } else if (keyword === "shortname") {
2355
+ metadata.shortname = stripWrapping(t[i++]);
2356
+ } else {
2357
+ throw new Error(
2358
+ "Parsing error: metadata. Unknown keyword " + keyword
2359
+ );
2360
+ }
2361
+ } else {
2362
+ throw new Error(
2363
+ "Parsing error: metadata. Expecting value for " + keyword
2364
+ );
2365
+ }
2366
+ }
2313
2367
  }
2314
- return role;
2315
- }
2368
+ return (ctx) => {
2369
+ ctx.metadata = metadata;
2370
+ return ctx;
2371
+ };
2372
+ };
2316
2373
 
2317
2374
  // src/ser-des/config/quantity.ts
2318
2375
  var NUMERIC = /^-?\d+(\.\d+)?([eE][+-]?\d+)?$/;
@@ -2928,6 +2985,10 @@ var parseProcess = function(id, data) {
2928
2985
  id,
2929
2986
  name: "",
2930
2987
  modality: "",
2988
+ // The workflow facets (smart TODO.roadmap/40 batch 5)
2989
+ phase: "",
2990
+ guards: [],
2991
+ machineSteps: [],
2931
2992
  actor: null,
2932
2993
  output: [],
2933
2994
  input: [],
@@ -2962,6 +3023,8 @@ var parseProcess = function(id, data) {
2962
3023
  windows: [],
2963
3024
  source: null,
2964
3025
  provisionRefs: [],
3026
+ outputRefs: [],
3027
+ inputRefs: [],
2965
3028
  _relations: {
2966
3029
  actor: "",
2967
3030
  output: [],
@@ -3002,6 +3065,12 @@ var parseProcess = function(id, data) {
3002
3065
  (keyword, value, peek) => {
3003
3066
  if (keyword === "modality") {
3004
3067
  result.modality = value();
3068
+ } else if (keyword === "phase") {
3069
+ result.phase = stripWrapping(value());
3070
+ } else if (keyword === "guard") {
3071
+ result.guards.push(unwrapped(value));
3072
+ } else if (keyword === "machine_steps") {
3073
+ result.machineSteps = tokenize(stripWrapping(value())).map(stripColon).map(stripWrapping).filter((s) => s.length > 0);
3005
3074
  } else if (keyword === "name") {
3006
3075
  result.name = unwrapped(value);
3007
3076
  } else if (keyword === "actor") {
@@ -3015,9 +3084,13 @@ var parseProcess = function(id, data) {
3015
3084
  } else if (keyword === "validate_measurement") {
3016
3085
  result.measure = tokenizePackage(value()).map((x) => unwrapBlock(x));
3017
3086
  } else if (keyword === "output") {
3018
- result._relations.output = tokenizePackage(value());
3087
+ result._relations.output = tokenizePackage(value()).map(
3088
+ (x) => stripWrapping(x)
3089
+ );
3019
3090
  } else if (keyword === "reference_data_registry") {
3020
- result._relations.input = tokenizePackage(value());
3091
+ result._relations.input = tokenizePackage(value()).map(
3092
+ (x) => stripWrapping(x)
3093
+ );
3021
3094
  } else if (keyword === "signature") {
3022
3095
  const sig = { inputs: [], outputs: [] };
3023
3096
  const st = tokenize(unwrapBlock(value()));
@@ -3125,6 +3198,12 @@ var resolveProcess = function(ctx, unresolved) {
3125
3198
  // name no declared `provision` construct (e.g. `/req/cs/*`
3126
3199
  // requirements) — the linter and the dumper read this list.
3127
3200
  provisionRefs: [..._relations.provision],
3201
+ // The raw process-I/O ids survive the same way (smart
3202
+ // TODO.roadmap/40 batch 5e): OIML SMART names entity-class STORE
3203
+ // ids here, which the `regs` resolver cannot see — without the raw
3204
+ // carriers the load → dump round-trip silently dropped them.
3205
+ outputRefs: [..._relations.output],
3206
+ inputRefs: [..._relations.input],
3128
3207
  actor: null,
3129
3208
  page: null
3130
3209
  };
@@ -3254,10 +3333,22 @@ var dumpProcess = function(process2, ctx) {
3254
3333
  if (process2.modality !== "") {
3255
3334
  out += " modality " + process2.modality + "\n";
3256
3335
  }
3257
- if (process2.input.length > 0) {
3336
+ if (process2.phase) {
3337
+ out += " phase " + dumpBareSafe(process2.phase) + "\n";
3338
+ }
3339
+ if (process2.guards && process2.guards.length > 0) {
3340
+ for (const g of process2.guards) {
3341
+ out += ' guard "' + escapeString(g) + '"\n';
3342
+ }
3343
+ }
3344
+ if (process2.machineSteps && process2.machineSteps.length > 0) {
3345
+ out += " machine_steps { " + process2.machineSteps.map(dumpBareSafe).join(" ") + " }\n";
3346
+ }
3347
+ const inputIds = process2.inputRefs && process2.inputRefs.length > 0 ? process2.inputRefs : process2.input.map((r) => r.id);
3348
+ if (inputIds.length > 0) {
3258
3349
  out += " reference_data_registry {\n";
3259
- for (const dr of process2.input) {
3260
- out += " " + dr.id + "\n";
3350
+ for (const id of inputIds) {
3351
+ out += " " + dumpBareSafe(id) + "\n";
3261
3352
  }
3262
3353
  out += " }\n";
3263
3354
  }
@@ -3275,10 +3366,11 @@ var dumpProcess = function(process2, ctx) {
3275
3366
  }
3276
3367
  out += " }\n";
3277
3368
  }
3278
- if (process2.output.length > 0) {
3369
+ const outputIds = process2.outputRefs && process2.outputRefs.length > 0 ? process2.outputRefs : process2.output.map((r) => r.id);
3370
+ if (outputIds.length > 0) {
3279
3371
  out += " output {\n";
3280
- for (const c of process2.output) {
3281
- out += " " + c.id + "\n";
3372
+ for (const id of outputIds) {
3373
+ out += " " + dumpBareSafe(id) + "\n";
3282
3374
  }
3283
3375
  out += " }\n";
3284
3376
  }
@@ -3697,6 +3789,75 @@ var dumpWorkflowConfig = function(c) {
3697
3789
  return out;
3698
3790
  };
3699
3791
 
3792
+ // src/ser-des/config/workflowStage.ts
3793
+ function readTokenList2(block) {
3794
+ return tokenize(stripWrapping(block)).map(stripColon).map(stripWrapping).filter((s) => s.length > 0);
3795
+ }
3796
+ function dumpTokenList2(keyword, ids) {
3797
+ if (ids.length === 0) {
3798
+ return "";
3799
+ }
3800
+ return " " + keyword + " { " + ids.map(dumpBareSafe).join(" ") + " }\n";
3801
+ }
3802
+ var parseWorkflowStage = (id, data) => {
3803
+ const stage = {
3804
+ id,
3805
+ label: "",
3806
+ description: "",
3807
+ elements: [],
3808
+ startEvent: "",
3809
+ endEvents: [],
3810
+ approvals: [],
3811
+ gateways: []
3812
+ };
3813
+ forEachEntry(
3814
+ data,
3815
+ (keyword, value) => {
3816
+ if (keyword === "label") {
3817
+ stage.label = stripWrapping(value());
3818
+ } else if (keyword === "description") {
3819
+ stage.description = stripWrapping(value());
3820
+ } else if (keyword === "elements") {
3821
+ stage.elements = readTokenList2(value());
3822
+ } else if (keyword === "start_event") {
3823
+ stage.startEvent = stripWrapping(value());
3824
+ } else if (keyword === "end_events") {
3825
+ stage.endEvents = readTokenList2(value());
3826
+ } else if (keyword === "approvals") {
3827
+ stage.approvals = readTokenList2(value());
3828
+ } else if (keyword === "gateways") {
3829
+ stage.gateways = readTokenList2(value());
3830
+ } else {
3831
+ return false;
3832
+ }
3833
+ return true;
3834
+ },
3835
+ { construct: "workflow_stage", id }
3836
+ );
3837
+ return (ctx) => {
3838
+ ctx.workflowStages[id] = stage;
3839
+ return ctx;
3840
+ };
3841
+ };
3842
+ var dumpWorkflowStage = function(s) {
3843
+ let out = "workflow_stage " + dumpBareSafe(s.id) + " {\n";
3844
+ if (s.label) {
3845
+ out += ' label "' + escapeString(s.label) + '"\n';
3846
+ }
3847
+ if (s.description) {
3848
+ out += ' description "' + escapeString(s.description) + '"\n';
3849
+ }
3850
+ out += dumpTokenList2("elements", s.elements);
3851
+ if (s.startEvent) {
3852
+ out += " start_event " + dumpBareSafe(s.startEvent) + "\n";
3853
+ }
3854
+ out += dumpTokenList2("end_events", s.endEvents);
3855
+ out += dumpTokenList2("approvals", s.approvals);
3856
+ out += dumpTokenList2("gateways", s.gateways);
3857
+ out += "}\n";
3858
+ return out;
3859
+ };
3860
+
3700
3861
  // src/ser-des/config/verificationPathway.ts
3701
3862
  var VERIFICATION_KINDS = [
3702
3863
  "initial",
@@ -18588,6 +18749,16 @@ var CONSTRUCTS = [
18588
18749
  parse: parseWorkflowConfig,
18589
18750
  dump: dumpWorkflowConfig
18590
18751
  }),
18752
+ // The named pipeline stage (smart TODO.roadmap/40 batch 5) — groups
18753
+ // the workflow constructs per stage; the members-resolve discipline
18754
+ // is C142's.
18755
+ defineConstruct({
18756
+ keyword: "workflow_stage",
18757
+ field: "workflowStages",
18758
+ takesID: true,
18759
+ parse: parseWorkflowStage,
18760
+ dump: dumpWorkflowStage
18761
+ }),
18591
18762
  defineConstruct({
18592
18763
  keyword: "approval",
18593
18764
  field: "approvals",
@@ -19582,6 +19753,9 @@ var MERGE_FIELDS = [
19582
19753
  // The certification workflow step register (smart TODO.roadmap/40
19583
19754
  // batch 3) — the rec-overlay deep merge (OVERLAY_DEEP_MERGE_FIELDS).
19584
19755
  "workflowConfigs",
19756
+ // The named pipeline stages (smart TODO.roadmap/40 batch 5) compose
19757
+ // with uses-no-redefine semantics.
19758
+ "workflowStages",
19585
19759
  // The verification pathways (smart TODO.roadmap/40 batch 3) compose
19586
19760
  // with uses-no-redefine semantics.
19587
19761
  "verificationPathways",
@@ -20591,6 +20765,9 @@ var TIER_BY_FIELD = {
20591
20765
  // The certification workflow step register (smart TODO.roadmap/40
20592
20766
  // batch 3) — operational wiring, tertiary.
20593
20767
  workflowConfigs: "tertiary",
20768
+ // The named pipeline stages (smart TODO.roadmap/40 batch 5) —
20769
+ // operational wiring, tertiary.
20770
+ workflowStages: "tertiary",
20594
20771
  // The verification pathways (smart TODO.roadmap/40 batch 3) —
20595
20772
  // operational wiring, tertiary.
20596
20773
  verificationPathways: "tertiary",
@@ -22033,6 +22210,33 @@ var CHECK_RULES = [
22033
22210
  "normal",
22034
22211
  "smart TODO.roadmap/40 batch 3 (the packages-as-SSOT epic)"
22035
22212
  ),
22213
+ // C142 (smart TODO.roadmap/40 batch 5; the packages-as-SSOT epic): the
22214
+ // gateway routing cascade — edge targets resolve to declared processes
22215
+ // (gated), exactly one default edge per edge-carrying gateway, the
22216
+ // default recommended last (warning). The workflow_stage members-
22217
+ // resolve legs ride this rule (step 5d).
22218
+ R(
22219
+ "C142",
22220
+ "gateway-edges-resolve",
22221
+ "composition",
22222
+ "error",
22223
+ "normal",
22224
+ "smart TODO.roadmap/40 batch 5 (the packages-as-SSOT epic)"
22225
+ ),
22226
+ // C143 (smart TODO.roadmap/40 batch 5; the packages-as-SSOT epic): the
22227
+ // first approval rule — actor/approve_by resolve to declared roles,
22228
+ // the approval_record entries to declared entity-class stores (the
22229
+ // dataclass `store { … }` names), per-register gated (the C58
22230
+ // doctrine). Reads the raw reference ids so unresolvable ids are still
22231
+ // checked — and still round-trip.
22232
+ R(
22233
+ "C143",
22234
+ "approval-references-resolve",
22235
+ "composition",
22236
+ "error",
22237
+ "normal",
22238
+ "smart TODO.roadmap/40 batch 5 (the packages-as-SSOT epic)"
22239
+ ),
22036
22240
  // ── quantities / time / duality (TODO.roadmap/06) ─────────────────
22037
22241
  R(
22038
22242
  "C32",
@@ -27589,6 +27793,108 @@ function checkPackage(dir, options = {}) {
27589
27793
  }
27590
27794
  }
27591
27795
  }
27796
+ {
27797
+ const gwProcessIds = new Set((standard.processes ?? []).map((p) => p.id));
27798
+ for (const g of standard.gateways ?? []) {
27799
+ if (g.gatewayType !== "exclusive_gateway") {
27800
+ continue;
27801
+ }
27802
+ const edges = g.edges ?? [];
27803
+ const where = `exclusive_gateway ${g.id}`;
27804
+ edges.forEach((e, i) => {
27805
+ if (gwProcessIds.size > 0 && !gwProcessIds.has(e.target)) {
27806
+ err(
27807
+ "C142",
27808
+ `${where}: edge ${i + 1} targets "${e.target}", which is not a declared process (gateway-edges-resolve)`
27809
+ );
27810
+ }
27811
+ });
27812
+ if (edges.length > 0) {
27813
+ const defaults = edges.map((e, i) => ({ e, i })).filter((x) => x.e.condition === "default");
27814
+ if (defaults.length === 0) {
27815
+ err(
27816
+ "C142",
27817
+ `${where}: no default edge \u2014 the first-match-wins cascade needs its catch-all (gateway-edges-resolve)`
27818
+ );
27819
+ } else if (defaults.length > 1) {
27820
+ err(
27821
+ "C142",
27822
+ `${where}: ${defaults.length} default edges \u2014 exactly one catch-all is allowed (gateway-edges-resolve)`
27823
+ );
27824
+ } else if (defaults[0].i !== edges.length - 1) {
27825
+ warn(
27826
+ "C142",
27827
+ `${where}: the default edge is not last \u2014 it shadows the edges after it in the first-match-wins cascade (gateway-edges-resolve)`
27828
+ );
27829
+ }
27830
+ }
27831
+ }
27832
+ const stageApprovalIds = new Set((standard.approvals ?? []).map((a) => a.id));
27833
+ const stageGatewayIds = new Set((standard.gateways ?? []).map((g) => g.id));
27834
+ for (const s of standard.workflowStages ?? []) {
27835
+ const where = `workflow_stage ${s.id}`;
27836
+ for (const el of s.elements ?? []) {
27837
+ if (gwProcessIds.size > 0 && !gwProcessIds.has(el)) {
27838
+ err(
27839
+ "C142",
27840
+ `${where}: element "${el}" is not a declared process (gateway-edges-resolve)`
27841
+ );
27842
+ }
27843
+ }
27844
+ for (const a of s.approvals ?? []) {
27845
+ if (stageApprovalIds.size > 0 && !stageApprovalIds.has(a)) {
27846
+ err(
27847
+ "C142",
27848
+ `${where}: approval "${a}" is not a declared approval (gateway-edges-resolve)`
27849
+ );
27850
+ }
27851
+ }
27852
+ for (const g of s.gateways ?? []) {
27853
+ if (stageGatewayIds.size > 0 && !stageGatewayIds.has(g)) {
27854
+ err(
27855
+ "C142",
27856
+ `${where}: gateway "${g}" is not a declared gateway (gateway-edges-resolve)`
27857
+ );
27858
+ }
27859
+ }
27860
+ }
27861
+ }
27862
+ {
27863
+ const approvalRoleIds = new Set((standard.roles ?? []).map((r) => r.id));
27864
+ const approvalStores = /* @__PURE__ */ new Set();
27865
+ for (const c of standard.dataclasses ?? []) {
27866
+ if (c.store) {
27867
+ for (const s of c.store.split(/\s+/)) {
27868
+ if (s) {
27869
+ approvalStores.add(s);
27870
+ }
27871
+ }
27872
+ }
27873
+ }
27874
+ for (const a of standard.approvals ?? []) {
27875
+ const where = `approval ${a.id}`;
27876
+ if (a.actorRef && approvalRoleIds.size > 0 && !approvalRoleIds.has(a.actorRef)) {
27877
+ err(
27878
+ "C143",
27879
+ `${where}: actor "${a.actorRef}" is not a declared role (approval-references-resolve)`
27880
+ );
27881
+ }
27882
+ if (a.approverRef && approvalRoleIds.size > 0 && !approvalRoleIds.has(a.approverRef)) {
27883
+ err(
27884
+ "C143",
27885
+ `${where}: approver "${a.approverRef}" is not a declared role (approval-references-resolve)`
27886
+ );
27887
+ }
27888
+ for (const store of a.recordRefs ?? []) {
27889
+ if (approvalStores.size > 0 && !approvalStores.has(store)) {
27890
+ err(
27891
+ "C143",
27892
+ `${where}: approval_record "${store}" is not a declared entity-class store (approval-references-resolve)`
27893
+ );
27894
+ }
27895
+ }
27896
+ }
27897
+ }
27592
27898
  for (const d of standard.duals ?? []) {
27593
27899
  if (d.attribute && !attrIds.has(d.attribute)) {
27594
27900
  err(