@primmel/primmel 1.21.12 → 1.21.13

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 (117) hide show
  1. package/dist/src/check-allowlist.d.ts +12 -0
  2. package/dist/src/check-allowlist.d.ts.map +1 -1
  3. package/dist/src/check-allowlist.js +35 -4
  4. package/dist/src/check-allowlist.js.map +1 -1
  5. package/dist/src/check-rules.d.ts.map +1 -1
  6. package/dist/src/check-rules.js +30 -0
  7. package/dist/src/check-rules.js.map +1 -1
  8. package/dist/src/check.d.ts +38 -0
  9. package/dist/src/check.d.ts.map +1 -1
  10. package/dist/src/check.js +1127 -4
  11. package/dist/src/check.js.map +1 -1
  12. package/dist/src/export/retrieval.d.ts +9 -1
  13. package/dist/src/export/retrieval.d.ts.map +1 -1
  14. package/dist/src/export/retrieval.js +29 -0
  15. package/dist/src/export/retrieval.js.map +1 -1
  16. package/dist/src/expressions/index.d.ts +69 -0
  17. package/dist/src/expressions/index.d.ts.map +1 -0
  18. package/dist/src/expressions/index.js +342 -0
  19. package/dist/src/expressions/index.js.map +1 -0
  20. package/dist/src/fmt.d.ts +11 -0
  21. package/dist/src/fmt.d.ts.map +1 -0
  22. package/dist/src/fmt.js +71 -0
  23. package/dist/src/fmt.js.map +1 -0
  24. package/dist/src/ser-des/config/calculation.d.ts.map +1 -1
  25. package/dist/src/ser-des/config/calculation.js +46 -0
  26. package/dist/src/ser-des/config/calculation.js.map +1 -1
  27. package/dist/src/ser-des/config/competenceKind.d.ts.map +1 -1
  28. package/dist/src/ser-des/config/competenceKind.js +9 -20
  29. package/dist/src/ser-des/config/competenceKind.js.map +1 -1
  30. package/dist/src/ser-des/config/conformanceTest.d.ts.map +1 -1
  31. package/dist/src/ser-des/config/conformanceTest.js +33 -6
  32. package/dist/src/ser-des/config/conformanceTest.js.map +1 -1
  33. package/dist/src/ser-des/config/constraint.d.ts.map +1 -1
  34. package/dist/src/ser-des/config/constraint.js +24 -2
  35. package/dist/src/ser-des/config/constraint.js.map +1 -1
  36. package/dist/src/ser-des/config/index.d.ts +7 -0
  37. package/dist/src/ser-des/config/index.d.ts.map +1 -1
  38. package/dist/src/ser-des/config/index.js +50 -0
  39. package/dist/src/ser-des/config/index.js.map +1 -1
  40. package/dist/src/ser-des/config/lmlAligned.d.ts +16 -0
  41. package/dist/src/ser-des/config/lmlAligned.d.ts.map +1 -0
  42. package/dist/src/ser-des/config/lmlAligned.js +337 -0
  43. package/dist/src/ser-des/config/lmlAligned.js.map +1 -0
  44. package/dist/src/ser-des/config/packageManifest.d.ts.map +1 -1
  45. package/dist/src/ser-des/config/packageManifest.js +3 -0
  46. package/dist/src/ser-des/config/packageManifest.js.map +1 -1
  47. package/dist/src/ser-des/config/process.d.ts.map +1 -1
  48. package/dist/src/ser-des/config/process.js +192 -0
  49. package/dist/src/ser-des/config/process.js.map +1 -1
  50. package/dist/src/ser-des/config/requirement.d.ts.map +1 -1
  51. package/dist/src/ser-des/config/requirement.js +123 -7
  52. package/dist/src/ser-des/config/requirement.js.map +1 -1
  53. package/dist/src/ser-des/config/symbol.d.ts.map +1 -1
  54. package/dist/src/ser-des/config/symbol.js +21 -0
  55. package/dist/src/ser-des/config/symbol.js.map +1 -1
  56. package/dist/src/ser-des/config/table.d.ts.map +1 -1
  57. package/dist/src/ser-des/config/table.js +7 -0
  58. package/dist/src/ser-des/config/table.js.map +1 -1
  59. package/dist/src/ser-des/config/uncertaintyBudget.d.ts +5 -0
  60. package/dist/src/ser-des/config/uncertaintyBudget.d.ts.map +1 -0
  61. package/dist/src/ser-des/config/uncertaintyBudget.js +211 -0
  62. package/dist/src/ser-des/config/uncertaintyBudget.js.map +1 -0
  63. package/dist/src/ser-des/config/verdict.d.ts.map +1 -1
  64. package/dist/src/ser-des/config/verdict.js +12 -2
  65. package/dist/src/ser-des/config/verdict.js.map +1 -1
  66. package/dist/src/ser-des/dump.d.ts.map +1 -1
  67. package/dist/src/ser-des/dump.js +46 -0
  68. package/dist/src/ser-des/dump.js.map +1 -1
  69. package/dist/src/ser-des/expression-carrier.d.ts +17 -0
  70. package/dist/src/ser-des/expression-carrier.d.ts.map +1 -0
  71. package/dist/src/ser-des/expression-carrier.js +72 -0
  72. package/dist/src/ser-des/expression-carrier.js.map +1 -0
  73. package/dist/src/ser-des/package.d.ts.map +1 -1
  74. package/dist/src/ser-des/package.js +54 -4
  75. package/dist/src/ser-des/package.js.map +1 -1
  76. package/dist/src/ser-des/parse.d.ts.map +1 -1
  77. package/dist/src/ser-des/parse.js +36 -2
  78. package/dist/src/ser-des/parse.js.map +1 -1
  79. package/dist/src/ser-des/shape-front-end.d.ts.map +1 -1
  80. package/dist/src/ser-des/shape-front-end.js +24 -5
  81. package/dist/src/ser-des/shape-front-end.js.map +1 -1
  82. package/dist/src/ser-des/types.d.ts +10 -0
  83. package/dist/src/ser-des/types.d.ts.map +1 -1
  84. package/dist/src/text-coverage.d.ts.map +1 -1
  85. package/dist/src/text-coverage.js +52 -0
  86. package/dist/src/text-coverage.js.map +1 -1
  87. package/dist/src/types/Calculation.d.ts +14 -0
  88. package/dist/src/types/Calculation.d.ts.map +1 -1
  89. package/dist/src/types/CompetenceKind.d.ts +6 -14
  90. package/dist/src/types/CompetenceKind.d.ts.map +1 -1
  91. package/dist/src/types/ConformanceTest.d.ts +5 -1
  92. package/dist/src/types/ConformanceTest.d.ts.map +1 -1
  93. package/dist/src/types/Constraint.d.ts +10 -1
  94. package/dist/src/types/Constraint.d.ts.map +1 -1
  95. package/dist/src/types/LmlAligned.d.ts +76 -0
  96. package/dist/src/types/LmlAligned.d.ts.map +1 -0
  97. package/dist/src/types/LmlAligned.js +8 -0
  98. package/dist/src/types/LmlAligned.js.map +1 -0
  99. package/dist/src/types/Package.d.ts +7 -0
  100. package/dist/src/types/Package.d.ts.map +1 -1
  101. package/dist/src/types/Requirement.d.ts +33 -0
  102. package/dist/src/types/Requirement.d.ts.map +1 -1
  103. package/dist/src/types/Standard.d.ts +12 -0
  104. package/dist/src/types/Standard.d.ts.map +1 -1
  105. package/dist/src/types/Symbol.d.ts +8 -0
  106. package/dist/src/types/Symbol.d.ts.map +1 -1
  107. package/dist/src/types/UncertaintyBudget.d.ts +68 -0
  108. package/dist/src/types/UncertaintyBudget.d.ts.map +1 -0
  109. package/dist/src/types/UncertaintyBudget.js +3 -0
  110. package/dist/src/types/UncertaintyBudget.js.map +1 -0
  111. package/dist/src/types/Verdict.d.ts +3 -1
  112. package/dist/src/types/Verdict.d.ts.map +1 -1
  113. package/dist/src/types/process.d.ts +52 -1
  114. package/dist/src/types/process.d.ts.map +1 -1
  115. package/dist-browser/index.mjs +2286 -1441
  116. package/dist-cli/primmel.mjs +2883 -76
  117. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // scripts/check.mts
4
- import { existsSync as existsSync8, readdirSync as readdirSync7, statSync as statSync4, writeFileSync } from "node:fs";
5
- import { join as join9 } from "node:path";
4
+ import { existsSync as existsSync8, readdirSync as readdirSync8, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
5
+ import { join as join10 } from "node:path";
6
6
 
7
7
  // src/check.ts
8
8
  import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
@@ -200,16 +200,44 @@ function parse(mmelString, parsers, options = {}) {
200
200
  continue;
201
201
  }
202
202
  if (cfg.takesID) {
203
- if (i + 1 > tokens.length) {
203
+ let formatTok;
204
+ if (cfg.takesFormat) {
205
+ const f = tokens[i++];
206
+ if (!["xml", "yaml", "json", "toml", "csv"].includes(f.value)) {
207
+ throw new Error(
208
+ `Parsing error: mapping. Unknown format "${f.value}" at line ${f.start.line} col ${f.start.col} (xml, yaml, json, toml, csv)`
209
+ );
210
+ }
211
+ formatTok = f;
212
+ }
213
+ if (i + 1 >= tokens.length) {
204
214
  throw new Error(
205
215
  `Keyword "${tok.value}" at line ${tok.start.line} col ${tok.start.col} expects an ID and payload, but only ${tokens.length - i + 1} token(s) remain.`
206
216
  );
207
217
  }
208
218
  const idTok = tokens[i++];
219
+ if (cfg.optionalTypedId && tokens[i]?.value === ":") {
220
+ const typeTok = tokens[i + 1];
221
+ const blockTok = tokens[i + 2];
222
+ if (!typeTok || !blockTok) {
223
+ throw new Error(
224
+ `Keyword "${tok.value}" at line ${tok.start.line} col ${tok.start.col} expects a type and payload, but too few token(s) remain.`
225
+ );
226
+ }
227
+ i += 3;
228
+ declarations.push({
229
+ keyword: tok.value,
230
+ id: idTok.value,
231
+ payload: `: ${typeTok.value} ${blockTok.value}`,
232
+ start: tok.start,
233
+ end: blockTok.end
234
+ });
235
+ continue;
236
+ }
209
237
  const payloadTok = tokens[i++];
210
238
  declarations.push({
211
239
  keyword: tok.value,
212
- id: idTok.value,
240
+ id: formatTok ? `${formatTok.value}:${idTok.value}` : idTok.value,
213
241
  payload: payloadTok.value,
214
242
  start: tok.start,
215
243
  end: payloadTok.end
@@ -269,6 +297,11 @@ function parseDeclarations(declarations, parsers, options = {}) {
269
297
  calculations: {},
270
298
  verdicts: {},
271
299
  referenceMaterials: {},
300
+ wireMappings: {},
301
+ stringFormats: {},
302
+ namespaces: {},
303
+ datums: {},
304
+ checks: {},
272
305
  testPointSets: {},
273
306
  commonTestConditions: {},
274
307
  competenceKinds: {},
@@ -277,6 +310,7 @@ function parseDeclarations(declarations, parsers, options = {}) {
277
310
  schemeTypes: {},
278
311
  predicates: {},
279
312
  constraints: {},
313
+ uncertaintyBudgets: {},
280
314
  discrepancyRecords: {},
281
315
  stateMachines: {},
282
316
  conformanceTests: {},
@@ -2495,6 +2529,369 @@ var parseMetadata = function(token) {
2495
2529
  return ctx;
2496
2530
  };
2497
2531
  };
2532
+ var dumpMetadata = function(meta) {
2533
+ let out = "metadata {\n";
2534
+ out += ' title "' + escapeString(meta.title) + '"\n';
2535
+ out += ' schema "' + escapeString(meta.schema) + '"\n';
2536
+ out += ' edition "' + escapeString(meta.edition) + '"\n';
2537
+ out += ' author "' + escapeString(meta.author) + '"\n';
2538
+ out += ' namespace "' + escapeString(meta.namespace) + '"\n';
2539
+ out += ' shortname "' + escapeString(meta.shortname ?? "") + '"\n';
2540
+ out += "}\n";
2541
+ return out;
2542
+ };
2543
+
2544
+ // src/expressions/index.ts
2545
+ var OPERATORS = [
2546
+ "->",
2547
+ "<=",
2548
+ ">=",
2549
+ "!=",
2550
+ "\u2260",
2551
+ "<",
2552
+ ">",
2553
+ "=",
2554
+ "+",
2555
+ "-",
2556
+ "*",
2557
+ "/",
2558
+ "(",
2559
+ ")",
2560
+ ",",
2561
+ ".",
2562
+ "|"
2563
+ ];
2564
+ var NAV_OPS = /* @__PURE__ */ new Set(["forAll", "exists", "select"]);
2565
+ function lex(src) {
2566
+ const tokens = [];
2567
+ let i = 0;
2568
+ while (i < src.length) {
2569
+ const c = src[i];
2570
+ if (/\s/.test(c)) {
2571
+ i += 1;
2572
+ continue;
2573
+ }
2574
+ if (c === "'") {
2575
+ let j = i + 1;
2576
+ while (j < src.length && src[j] !== "'") {
2577
+ j += 1;
2578
+ }
2579
+ if (j >= src.length) {
2580
+ throw new Error(`expression: unterminated string at offset ${i}`);
2581
+ }
2582
+ tokens.push({ kind: "str", value: src.slice(i + 1, j) });
2583
+ i = j + 1;
2584
+ continue;
2585
+ }
2586
+ if (/[0-9]/.test(c)) {
2587
+ let j = i;
2588
+ while (j < src.length && /[0-9.]/.test(src[j])) {
2589
+ j += 1;
2590
+ }
2591
+ tokens.push({ kind: "num", value: Number(src.slice(i, j)) });
2592
+ i = j;
2593
+ continue;
2594
+ }
2595
+ if (/[A-Za-z_]/.test(c)) {
2596
+ let j = i;
2597
+ while (j < src.length && /[A-Za-z0-9_.]/.test(src[j])) {
2598
+ j += 1;
2599
+ }
2600
+ tokens.push({ kind: "name", value: src.slice(i, j) });
2601
+ i = j;
2602
+ continue;
2603
+ }
2604
+ const two = src.slice(i, i + 2);
2605
+ if (OPERATORS.includes(two)) {
2606
+ tokens.push({ kind: "op", value: two });
2607
+ i += 2;
2608
+ continue;
2609
+ }
2610
+ if (OPERATORS.includes(c)) {
2611
+ tokens.push({ kind: "op", value: c });
2612
+ i += 1;
2613
+ continue;
2614
+ }
2615
+ throw new Error(`expression: unexpected character "${c}" at offset ${i}`);
2616
+ }
2617
+ return tokens;
2618
+ }
2619
+ var BINARY_LEVELS = [
2620
+ ["implies"],
2621
+ ["or"],
2622
+ ["xor"],
2623
+ ["and"],
2624
+ ["<=", ">=", "<", ">", "=", "!=", "\u2260"],
2625
+ ["+", "-"],
2626
+ ["*", "/"]
2627
+ ];
2628
+ var WORD_BINOPS = /* @__PURE__ */ new Set(["implies", "or", "xor", "and"]);
2629
+ var ExprParser = class {
2630
+ tokens;
2631
+ pos = 0;
2632
+ constructor(tokens) {
2633
+ this.tokens = tokens;
2634
+ }
2635
+ peek() {
2636
+ return this.tokens[this.pos];
2637
+ }
2638
+ take() {
2639
+ const tok = this.tokens[this.pos];
2640
+ if (tok === void 0) {
2641
+ throw new Error("expression: unexpected end");
2642
+ }
2643
+ this.pos += 1;
2644
+ return tok;
2645
+ }
2646
+ parse() {
2647
+ const ast = this.parseLevel(0);
2648
+ if (this.pos !== this.tokens.length) {
2649
+ throw new Error(`expression: trailing tokens at position ${this.pos}`);
2650
+ }
2651
+ return ast;
2652
+ }
2653
+ parseLevel(level) {
2654
+ if (level >= BINARY_LEVELS.length) {
2655
+ return this.parseUnary();
2656
+ }
2657
+ let left = this.parseLevel(level + 1);
2658
+ for (; ; ) {
2659
+ const tok = this.peek();
2660
+ const op = tok?.kind === "op" ? tok.value : tok?.kind === "name" && WORD_BINOPS.has(tok.value) ? tok.value : void 0;
2661
+ if (op === void 0 || !BINARY_LEVELS[level].includes(op)) {
2662
+ return left;
2663
+ }
2664
+ this.take();
2665
+ const right = this.parseLevel(level + 1);
2666
+ left = { type: "binop", op, left, right };
2667
+ }
2668
+ }
2669
+ parseUnary() {
2670
+ const tok = this.peek();
2671
+ if (tok?.kind === "name" && (tok.value === "not" || tok.value === "-")) {
2672
+ this.take();
2673
+ return { type: "unop", op: tok.value, operand: this.parseUnary() };
2674
+ }
2675
+ if (tok?.kind === "op" && tok.value === "-") {
2676
+ this.take();
2677
+ return { type: "unop", op: "-", operand: this.parseUnary() };
2678
+ }
2679
+ return this.parsePrimary();
2680
+ }
2681
+ parsePrimary() {
2682
+ const tok = this.take();
2683
+ if (tok.kind === "num") {
2684
+ return { type: "num", value: tok.value };
2685
+ }
2686
+ if (tok.kind === "str") {
2687
+ return { type: "str", value: tok.value };
2688
+ }
2689
+ if (tok.kind === "op" && tok.value === "(") {
2690
+ const inner = this.parseLevel(0);
2691
+ const close = this.take();
2692
+ if (close.kind !== "op" || close.value !== ")") {
2693
+ throw new Error("expression: expected closing parenthesis");
2694
+ }
2695
+ return inner;
2696
+ }
2697
+ if (tok.kind === "name") {
2698
+ const segs = [tok.value];
2699
+ while (this.peek()?.kind === "op" && this.peek().value === ".") {
2700
+ this.take();
2701
+ const seg = this.take();
2702
+ if (seg.kind !== "name") {
2703
+ throw new Error('expression: expected a path segment after "."');
2704
+ }
2705
+ segs.push(seg.value);
2706
+ }
2707
+ const next = this.peek();
2708
+ if (next?.kind === "op" && next.value === "(" && !WORD_BINOPS.has(segs[0])) {
2709
+ this.take();
2710
+ const args2 = [];
2711
+ const closing = this.peek();
2712
+ if (closing?.kind === "op" && closing.value === ")") {
2713
+ this.take();
2714
+ return { type: "call", callee: segs.join("."), args: args2 };
2715
+ }
2716
+ for (; ; ) {
2717
+ args2.push(this.parseLevel(0));
2718
+ const sep = this.peek();
2719
+ if (sep?.kind === "op" && sep.value === ",") {
2720
+ this.take();
2721
+ continue;
2722
+ }
2723
+ break;
2724
+ }
2725
+ const close = this.take();
2726
+ if (close.kind !== "op" || close.value !== ")") {
2727
+ throw new Error("expression: expected closing parenthesis");
2728
+ }
2729
+ return { type: "call", callee: segs.join("."), args: args2 };
2730
+ }
2731
+ const arrow = this.peek();
2732
+ if (arrow?.kind === "op" && arrow.value === "->") {
2733
+ this.take();
2734
+ const opTok = this.take();
2735
+ if (opTok.kind !== "name" || !NAV_OPS.has(opTok.value)) {
2736
+ throw new Error(
2737
+ "expression: expected a collection iterator (forAll | exists | select)"
2738
+ );
2739
+ }
2740
+ if (this.peek()?.kind !== "op" || this.peek().value !== "(") {
2741
+ throw new Error("expression: expected ( after the iterator");
2742
+ }
2743
+ this.take();
2744
+ const varTok = this.take();
2745
+ if (varTok.kind !== "name") {
2746
+ throw new Error("expression: expected the lambda parameter");
2747
+ }
2748
+ if (this.peek()?.kind !== "op" || this.peek().value !== "|") {
2749
+ throw new Error("expression: expected | after the parameter");
2750
+ }
2751
+ this.take();
2752
+ const body = this.parseLevel(0);
2753
+ const close = this.take();
2754
+ if (close.kind !== "op" || close.value !== ")") {
2755
+ throw new Error("expression: expected closing parenthesis");
2756
+ }
2757
+ return {
2758
+ type: "nav",
2759
+ source: segs.join("."),
2760
+ op: opTok.value,
2761
+ var: varTok.value,
2762
+ body
2763
+ };
2764
+ }
2765
+ return { type: "name", path: segs };
2766
+ }
2767
+ throw new Error(`expression: unexpected token "${String(tok.value)}"`);
2768
+ }
2769
+ };
2770
+ function parseExpression(src) {
2771
+ return new ExprParser(lex(src)).parse();
2772
+ }
2773
+ function canonicalizeExpression(raw) {
2774
+ const body = raw.trim();
2775
+ if (body.length === 0) {
2776
+ throw new Error("expression: the block is empty");
2777
+ }
2778
+ return renderExpression(parseExpression(body));
2779
+ }
2780
+ function freeIdentifiers(ast) {
2781
+ const out = { names: [], calls: [] };
2782
+ const walk = (node, bound) => {
2783
+ switch (node.type) {
2784
+ case "num":
2785
+ return;
2786
+ case "str":
2787
+ return;
2788
+ case "name": {
2789
+ if (bound.has(node.path[0].split(".")[0])) {
2790
+ return;
2791
+ }
2792
+ out.names.push(node.path.join("."));
2793
+ return;
2794
+ }
2795
+ case "call":
2796
+ out.calls.push(node.callee);
2797
+ for (const a of node.args) {
2798
+ walk(a, bound);
2799
+ }
2800
+ return;
2801
+ case "unop":
2802
+ walk(node.operand, bound);
2803
+ return;
2804
+ case "binop":
2805
+ walk(node.left, bound);
2806
+ walk(node.right, bound);
2807
+ return;
2808
+ case "nav": {
2809
+ const inner = new Set(bound);
2810
+ inner.add(node["var"]);
2811
+ walk({ type: "name", path: [node.source] }, bound);
2812
+ walk(node.body, inner);
2813
+ return;
2814
+ }
2815
+ }
2816
+ };
2817
+ walk(ast, /* @__PURE__ */ new Set());
2818
+ return out;
2819
+ }
2820
+ function renderExpression(ast) {
2821
+ switch (ast.type) {
2822
+ case "num":
2823
+ return String(ast.value);
2824
+ case "str":
2825
+ return "'" + ast.value + "'";
2826
+ case "name":
2827
+ return ast.path.join(".");
2828
+ case "call":
2829
+ return ast.callee + "(" + ast.args.map(renderExpression).join(", ") + ")";
2830
+ case "unop": {
2831
+ const inner = renderExpression(ast.operand);
2832
+ return ast.op + (ast.operand.type === "binop" ? " (" + inner + ")" : " " + inner);
2833
+ }
2834
+ case "nav":
2835
+ return ast.source + " -> " + ast.op + "(" + ast["var"] + " | " + renderExpression(ast.body) + ")";
2836
+ case "binop":
2837
+ return renderExpression(ast.left) + " " + ast.op + " " + renderExpression(ast.right);
2838
+ }
2839
+ }
2840
+
2841
+ // src/ser-des/expression-carrier.ts
2842
+ function readExpressionCarrier(token, what) {
2843
+ if (token.startsWith("{")) {
2844
+ try {
2845
+ return {
2846
+ source: canonicalizeExpression(unwrapBlock(token)),
2847
+ inline: true
2848
+ };
2849
+ } catch (e) {
2850
+ throw new Error(
2851
+ `Parsing error: ${what}: ${e.message ?? String(e)}`
2852
+ );
2853
+ }
2854
+ }
2855
+ if (token.length >= 2 && token.charAt(0) === '"') {
2856
+ return {
2857
+ source: unescapeString(token.substr(1, token.length - 2)),
2858
+ inline: false
2859
+ };
2860
+ }
2861
+ return { source: token, inline: false };
2862
+ }
2863
+ function dumpExpressionBlock(keyword, source, indent) {
2864
+ const body = source.split("\n").map((l) => indent + " " + l).join("\n");
2865
+ return indent + keyword + " {\n" + body + "\n" + indent + "}\n";
2866
+ }
2867
+ function readArgsBlock(token) {
2868
+ const at = tokenize(token);
2869
+ const args2 = [];
2870
+ let k = 0;
2871
+ while (k < at.length) {
2872
+ const name = unescapeStringOrBare(at[k++]);
2873
+ if (k >= at.length) {
2874
+ throw new Error(`limit args: "${name}" binds to nothing`);
2875
+ }
2876
+ if (at[k] !== "<-") {
2877
+ throw new Error(
2878
+ `limit args: expected "<-" after "${name}" (name <- source)`
2879
+ );
2880
+ }
2881
+ k += 1;
2882
+ if (k >= at.length) {
2883
+ throw new Error(`limit args: "${name}" binds to nothing`);
2884
+ }
2885
+ args2.push({ name, source: unescapeStringOrBare(at[k++]) });
2886
+ }
2887
+ return args2;
2888
+ }
2889
+ function unescapeStringOrBare(t) {
2890
+ if (t.length >= 2 && t.charAt(0) === '"' && t.charAt(t.length - 1) === '"') {
2891
+ return unescapeString(t.substr(1, t.length - 2));
2892
+ }
2893
+ return t;
2894
+ }
2498
2895
 
2499
2896
  // src/ser-des/config/quantity.ts
2500
2897
  var NUMERIC = /^-?\d+(\.\d+)?([eE][+-]?\d+)?$/;
@@ -2987,10 +3384,20 @@ var STEP_KINDS = /* @__PURE__ */ new Set([
2987
3384
  "timer_event",
2988
3385
  "signal_event"
2989
3386
  ]);
3387
+ function parseCallBindings(block) {
3388
+ return parseParamList(unwrapBlock(block)).map((pr) => ({
3389
+ param: pr.name,
3390
+ bind: pr.type
3391
+ }));
3392
+ }
2990
3393
  function parseStepBody(id, kind, block) {
2991
3394
  const step = {
2992
3395
  id,
2993
3396
  kind,
3397
+ signatureBlock: "",
3398
+ sigInputs: [],
3399
+ sigOutputs: [],
3400
+ completion: "",
2994
3401
  executor: "",
2995
3402
  role: "",
2996
3403
  capture: "",
@@ -3260,6 +3667,112 @@ var parseProcess = function(id, data) {
3260
3667
  result._relations.page = value();
3261
3668
  } else if (keyword === "validate_provision") {
3262
3669
  result._relations.provision = tokenizePackage(value());
3670
+ } else if (keyword === "step" || keyword === "binding") {
3671
+ const sid = stripWrapping(value());
3672
+ const blockTok = value();
3673
+ if (keyword === "step") {
3674
+ const raw = blockTok !== void 0 && blockTok.startsWith("{") ? unwrapBlock(blockTok) : blockTok ?? "";
3675
+ const st = {
3676
+ id: sid,
3677
+ kind: "action",
3678
+ executor: "",
3679
+ role: "",
3680
+ capture: "",
3681
+ reads: [],
3682
+ writes: [],
3683
+ fires: "",
3684
+ calls: "",
3685
+ callIn: [],
3686
+ callOut: [],
3687
+ wait: "",
3688
+ period: "",
3689
+ signal: "",
3690
+ signatureBlock: raw,
3691
+ sigInputs: [],
3692
+ sigOutputs: [],
3693
+ completion: "",
3694
+ description: ""
3695
+ };
3696
+ const tt = tokenizePackage(raw);
3697
+ let ti = 0;
3698
+ while (ti < tt.length) {
3699
+ const tc = tt[ti++];
3700
+ if (ti >= tt.length) {
3701
+ break;
3702
+ }
3703
+ if (tc === "inputs" || tc === "outputs") {
3704
+ const pairs = parseParamList(unwrapBlock(tt[ti++]));
3705
+ const names = pairs.map((pr) => pr.name);
3706
+ if (tc === "inputs") {
3707
+ st.sigInputs = names;
3708
+ } else {
3709
+ st.sigOutputs = names;
3710
+ }
3711
+ } else if (tc === "requires") {
3712
+ const ids = tokenizePackage(unwrapBlock(tt[ti++])).map(stripWrapping).filter((x) => x.length > 0);
3713
+ (result.stepRequires ??= []).push(...ids);
3714
+ } else if (tc === "completion") {
3715
+ if (tt[ti] === "check") {
3716
+ ti += 1;
3717
+ st.completionGate = stripWrapping(tt[ti++]);
3718
+ const bt = tokenizePackage(unwrapBlock(tt[ti++]));
3719
+ let bi = 0;
3720
+ while (bi < bt.length) {
3721
+ const bc = bt[bi++];
3722
+ if (bi >= bt.length) {
3723
+ break;
3724
+ }
3725
+ if (bc === "expression") {
3726
+ const c = readExpressionCarrier(
3727
+ bt[bi++],
3728
+ "step completion"
3729
+ );
3730
+ st.completion = c.source;
3731
+ st.completionBound = c.inline || void 0;
3732
+ } else {
3733
+ bi = skipUnknownEntry(bt, bi);
3734
+ }
3735
+ }
3736
+ } else {
3737
+ const c = readExpressionCarrier(tt[ti++], "step completion");
3738
+ st.completion = c.source;
3739
+ st.completionBound = c.inline || void 0;
3740
+ }
3741
+ } else if (tc === "calls") {
3742
+ st.calls = stripWrapping(tt[ti++]);
3743
+ if (ti < tt.length && tt[ti] === "with") {
3744
+ const wt = tokenize(unwrapBlock(tt[ti++]));
3745
+ let wk = 0;
3746
+ while (wk < wt.length) {
3747
+ const wc = wt[wk++];
3748
+ if (wk >= wt.length) {
3749
+ break;
3750
+ }
3751
+ if (wc === "in") {
3752
+ st.callIn.push(...parseCallBindings(wt[wk++]));
3753
+ } else if (wc === "out") {
3754
+ st.callOut.push(...parseCallBindings(wt[wk++]));
3755
+ } else {
3756
+ unwrapBlock(wt[wk++]);
3757
+ }
3758
+ }
3759
+ }
3760
+ } else if (tc === "description") {
3761
+ st.description = stripWrapping(tt[ti++]);
3762
+ } else {
3763
+ ti = skipUnknownEntry(tt, ti);
3764
+ }
3765
+ }
3766
+ (result.steps ??= []).push(st);
3767
+ } else {
3768
+ (result.bindings ??= []).push({
3769
+ id: sid,
3770
+ block: blockTok !== void 0 && blockTok.startsWith("{") ? unwrapBlock(blockTok) : blockTok ?? ""
3771
+ });
3772
+ }
3773
+ } else if (keyword === "requires") {
3774
+ const inner = tokenizePackage(unwrapBlock(value()));
3775
+ (result.stepRequires ??= []).push(...inner.map(stripWrapping));
3263
3776
  } else if (keyword === "validate_measurement") {
3264
3777
  result.measure = tokenizePackage(value()).map((x) => unwrapBlock(x));
3265
3778
  } else if (keyword === "output") {
@@ -3417,6 +3930,25 @@ var resolveProcess = function(ctx, unresolved) {
3417
3930
  }
3418
3931
  return p;
3419
3932
  };
3933
+ function indentBlock(block) {
3934
+ return block.split("\n").map((line) => line ? " " + line : line).join("\n");
3935
+ }
3936
+ function dumpProcessTree(process2, lookup, nested = false) {
3937
+ let out = dumpProcess(process2, { nested });
3938
+ if (process2.children.length > 0) {
3939
+ const childBlocks = [];
3940
+ for (const childId of process2.children) {
3941
+ const child = lookup.get(childId);
3942
+ if (child) {
3943
+ childBlocks.push(indentBlock(dumpProcessTree(child, lookup, true)));
3944
+ }
3945
+ }
3946
+ if (childBlocks.length > 0) {
3947
+ out = out.replace(/\n}\n$/, "\n" + childBlocks.join("\n") + "}\n");
3948
+ }
3949
+ }
3950
+ return out;
3951
+ }
3420
3952
  function dumpParamList(params) {
3421
3953
  return params.map(
3422
3954
  (p) => p.name + (p.type ? " : " + p.type : "") + (p.initial !== void 0 ? " = " + dumpQuantityValue(p.initial) : "")
@@ -3531,6 +4063,26 @@ var dumpProcess = function(process2, ctx) {
3531
4063
  if (process2.machineSteps && process2.machineSteps.length > 0) {
3532
4064
  out += " machine_steps { " + process2.machineSteps.map(dumpBareSafe).join(" ") + " }\n";
3533
4065
  }
4066
+ for (const st of process2.steps ?? []) {
4067
+ if (st.signatureBlock) {
4068
+ const lines = st.signatureBlock.split("\n").map((l) => l.trim()).filter((l) => l !== "");
4069
+ out += " step " + st.id + " {\n";
4070
+ for (const line of lines) {
4071
+ out += " " + line + "\n";
4072
+ }
4073
+ out += " }\n";
4074
+ }
4075
+ }
4076
+ for (const b of process2.bindings ?? []) {
4077
+ out += " binding " + b.id + " {\n";
4078
+ for (const line of b.block.split("\n")) {
4079
+ out += line === "" ? "\n" : " " + line + "\n";
4080
+ }
4081
+ out += " }\n";
4082
+ }
4083
+ for (const req of process2.stepRequires ?? []) {
4084
+ out += " requires { " + req + " }\n";
4085
+ }
3534
4086
  const inputIds = process2.inputRefs && process2.inputRefs.length > 0 ? process2.inputRefs : process2.input.map((r) => r.id);
3535
4087
  if (inputIds.length > 0) {
3536
4088
  out += " reference_data_registry {\n";
@@ -5270,6 +5822,11 @@ function parseColumnDefs(block) {
5270
5822
  if (!name) {
5271
5823
  break;
5272
5824
  }
5825
+ if (i < t.length && t[i] === "{") {
5826
+ throw new Error(
5827
+ `Parsing error: table. Column "${name}": the old columns dialect (colN { name ... type ... }) is retired \u2014 write the canonical form: ${name === "" ? "name" : name}: type "unit"`
5828
+ );
5829
+ }
5273
5830
  if (i < t.length && t[i] === ":") {
5274
5831
  i++;
5275
5832
  }
@@ -6695,6 +7252,7 @@ var parseSymbol = function(id, data) {
6695
7252
  type: "number",
6696
7253
  unit: "1",
6697
7254
  latex: "",
7255
+ renders: [],
6698
7256
  values: [],
6699
7257
  series: null,
6700
7258
  kind: "",
@@ -6746,6 +7304,20 @@ var parseSymbol = function(id, data) {
6746
7304
  result.unit = unwrapped(value);
6747
7305
  } else if (command === "latex") {
6748
7306
  result.latex = unwrapped(value);
7307
+ } else if (command === "render") {
7308
+ const notation = stripWrapping(value());
7309
+ const text = peek() !== void 0 ? stripWrapping(value()) : "";
7310
+ if (!result.renders) {
7311
+ result.renders = [];
7312
+ }
7313
+ if (["asciimath", "latex", "unicodemath", "mathml", "omml"].includes(
7314
+ notation
7315
+ )) {
7316
+ result.renders.push({ notation, text });
7317
+ if (notation === "latex" && !result.latex) {
7318
+ result.latex = text;
7319
+ }
7320
+ }
6749
7321
  } else if (command === "values") {
6750
7322
  const v = value();
6751
7323
  result.values = v.startsWith("{") ? tokenizePackage(v).map(stripWrapping) : [stripWrapping(v)];
@@ -6826,6 +7398,9 @@ var dumpSymbol = function(s) {
6826
7398
  if (s.latex) {
6827
7399
  out += ' latex "' + escapeString(s.latex) + '"\n';
6828
7400
  }
7401
+ for (const r of s.renders ?? []) {
7402
+ out += " render " + r.notation + ' "' + escapeString(r.text) + '"\n';
7403
+ }
6829
7404
  if (s.values.length > 0) {
6830
7405
  out += " values { " + s.values.map(dumpBareSafe).join(" ") + " }\n";
6831
7406
  }
@@ -6971,6 +7546,23 @@ var parseCalculation = function(id, data) {
6971
7546
  result.description = unwrapBlock(t[i++]);
6972
7547
  } else if (command === "expression") {
6973
7548
  result.expression = unwrapBlock(t[i++]);
7549
+ } else if (command === "math") {
7550
+ const inner = tokenizePackage(unwrapBlock(t[i++]));
7551
+ let notation = "";
7552
+ let formula = "";
7553
+ let j = 0;
7554
+ while (j < inner.length) {
7555
+ const k = inner[j++];
7556
+ if (j >= inner.length) {
7557
+ break;
7558
+ }
7559
+ if (k === "notation") {
7560
+ notation = stripWrapping(inner[j++]);
7561
+ } else if (k === "formula") {
7562
+ formula = stripWrapping(inner[j++]);
7563
+ }
7564
+ }
7565
+ result.math = { notation, formula };
6974
7566
  } else if (command === "reference") {
6975
7567
  result._relations.ref = tokenizePackage(t[i++]);
6976
7568
  } else if (command === "ref") {
@@ -7287,6 +7879,23 @@ function parseVariant(vid, block, calcId) {
7287
7879
  variant.params = tokenize(stripWrapping(t[i++])).map(stripWrapping).filter((s) => s.length > 0);
7288
7880
  } else if (cmd === "expression") {
7289
7881
  variant.expression = stripWrapping(t[i++]);
7882
+ } else if (cmd === "math") {
7883
+ const inner = tokenizePackage(unwrapBlock(t[i++]));
7884
+ let notation = "";
7885
+ let formula = "";
7886
+ let j = 0;
7887
+ while (j < inner.length) {
7888
+ const k = inner[j++];
7889
+ if (j >= inner.length) {
7890
+ break;
7891
+ }
7892
+ if (k === "notation") {
7893
+ notation = stripWrapping(inner[j++]);
7894
+ } else if (k === "formula") {
7895
+ formula = stripWrapping(inner[j++]);
7896
+ }
7897
+ }
7898
+ variant.math = { notation, formula };
7290
7899
  } else if (cmd === "lookup") {
7291
7900
  variant.lookup = parseLookup(unwrapBlock(t[i++]));
7292
7901
  } else if (cmd === "profile") {
@@ -7427,6 +8036,12 @@ var dumpCalculation = function(c) {
7427
8036
  if (c.expression) {
7428
8037
  out += ' expression "' + escapeString(c.expression) + '"\n';
7429
8038
  }
8039
+ if (c.math) {
8040
+ out += " math {\n";
8041
+ out += " notation " + c.math.notation + "\n";
8042
+ out += ' formula "' + escapeString(c.math.formula) + '"\n';
8043
+ out += " }\n";
8044
+ }
7430
8045
  if (c.params && c.params.length > 0) {
7431
8046
  out += " params { " + c.params.join(" ") + " }\n";
7432
8047
  }
@@ -8605,7 +9220,7 @@ function parseRequiredCompetence(block) {
8605
9220
  const entry = {
8606
9221
  kind: stripWrapping(t[i++]),
8607
9222
  range: null,
8608
- methodStandard: "",
9223
+ methodRef: "",
8609
9224
  resolution: null,
8610
9225
  stability: null,
8611
9226
  description: ""
@@ -8638,8 +9253,8 @@ function parseRequiredCompetence(block) {
8638
9253
  }
8639
9254
  }
8640
9255
  entry.range = range;
8641
- } else if (cc === "method_standard") {
8642
- entry.methodStandard = stripWrapping(ct[j++]);
9256
+ } else if (cc === "method_ref") {
9257
+ entry.methodRef = stripWrapping(ct[j++]);
8643
9258
  } else if (cc === "resolution") {
8644
9259
  entry.resolution = readQuantity(unwrapBlock(ct[j++]));
8645
9260
  } else if (cc === "stability") {
@@ -8682,8 +9297,8 @@ function dumpRequiredCompetence(entries) {
8682
9297
  line += ' unit "' + escapeString(e.range.unit) + '" }\n';
8683
9298
  out += line;
8684
9299
  }
8685
- if (e.methodStandard) {
8686
- out += ' method_standard "' + escapeString(e.methodStandard) + '"\n';
9300
+ if (e.methodRef) {
9301
+ out += " method_ref " + e.methodRef + "\n";
8687
9302
  }
8688
9303
  out += dumpQuantity("resolution", e.resolution);
8689
9304
  out += dumpQuantity("stability", e.stability);
@@ -8706,8 +9321,7 @@ var parseCompetenceKind = function(id, data) {
8706
9321
  id,
8707
9322
  label: "",
8708
9323
  definition: "",
8709
- source: null,
8710
- methodStandards: []
9324
+ source: null
8711
9325
  };
8712
9326
  const t = tokenizePackage(data);
8713
9327
  let i = 0;
@@ -8724,14 +9338,6 @@ var parseCompetenceKind = function(id, data) {
8724
9338
  result.definition = readValue(t[i++]);
8725
9339
  } else if (keyword === "source") {
8726
9340
  result.source = readSource(unwrapBlock(t[i++]));
8727
- } else if (keyword === "method_standard") {
8728
- const stdId = stripWrapping(t[i++]);
8729
- if (i >= t.length) {
8730
- throw new Error(
8731
- `Parsing error: competence_kind. ID ${id}: Expecting title for method_standard ${stdId}`
8732
- );
8733
- }
8734
- result.methodStandards.push({ id: stdId, title: readValue(t[i++]) });
8735
9341
  } else if (keyword === "ref") {
8736
9342
  const rr = parseRef(t, i, stripWrapping, unwrapBlock);
8737
9343
  if (!foldRefIntoLegacy(result, rr.ref)) {
@@ -8762,9 +9368,6 @@ var dumpCompetenceKind = function(k) {
8762
9368
  if (k.source && (k.source.doc || k.source.clause)) {
8763
9369
  out += ' source { doc "' + escapeString(k.source.doc) + '" clause "' + escapeString(k.source.clause) + '"' + (k.source.fragment ? ' fragment "' + escapeString(k.source.fragment) + '"' : "") + " }\n";
8764
9370
  }
8765
- for (const ms of k.methodStandards) {
8766
- out += " method_standard " + ms.id + ' "' + escapeString(ms.title) + '"\n';
8767
- }
8768
9371
  out += dumpCorrespondences(
8769
9372
  k.correspondences,
8770
9373
  " ",
@@ -8825,7 +9428,9 @@ function parseTestVariables(block) {
8825
9428
  } else if (vc === "source") {
8826
9429
  v.source = stripWrapping(vt[j++]);
8827
9430
  } else if (vc === "derivation") {
8828
- v.derivation = stripWrapping(vt[j++]);
9431
+ const c = readExpressionCarrier(vt[j++], "test variable derivation");
9432
+ v.derivation = c.source;
9433
+ v.derivationBound = c.inline || void 0;
8829
9434
  } else if (vc === "description") {
8830
9435
  v.description = stripWrapping(vt[j++]);
8831
9436
  } else if (vc === "item_type") {
@@ -8885,7 +9490,9 @@ function parsePreconditions(block) {
8885
9490
  break;
8886
9491
  }
8887
9492
  if (pc === "check") {
8888
- p.check = stripWrapping(pt[j++]);
9493
+ const c = readExpressionCarrier(pt[j++], "precondition check");
9494
+ p.check = c.source;
9495
+ p.checkBound = c.inline || void 0;
8889
9496
  } else if (pc === "description") {
8890
9497
  p.description = stripWrapping(pt[j++]);
8891
9498
  } else if (pc === "on_violation") {
@@ -9651,8 +10258,17 @@ var dumpConformanceTest = function(ct) {
9651
10258
  if (v.source) {
9652
10259
  line += "source " + v.source + " ";
9653
10260
  }
10261
+ let derivationBlock = "";
9654
10262
  if (v.derivation) {
9655
- line += 'derivation "' + escapeString(v.derivation) + '" ';
10263
+ if (v.derivationBound) {
10264
+ derivationBlock = dumpExpressionBlock(
10265
+ "derivation",
10266
+ v.derivation,
10267
+ " "
10268
+ );
10269
+ } else {
10270
+ line += 'derivation "' + escapeString(v.derivation) + '" ';
10271
+ }
9656
10272
  }
9657
10273
  if (v.description) {
9658
10274
  line += 'description "' + escapeString(v.description) + '" ';
@@ -9679,7 +10295,11 @@ var dumpConformanceTest = function(ct) {
9679
10295
  }
9680
10296
  line += pv + "} ";
9681
10297
  }
9682
- out += line + "}\n";
10298
+ if (derivationBlock) {
10299
+ out += line + "\n" + derivationBlock + " }\n";
10300
+ } else {
10301
+ out += line + "}\n";
10302
+ }
9683
10303
  }
9684
10304
  out += " }\n";
9685
10305
  }
@@ -9707,8 +10327,13 @@ var dumpConformanceTest = function(ct) {
9707
10327
  out += " preconditions {\n";
9708
10328
  for (const p of ct.preconditions) {
9709
10329
  let line = " precondition " + p.id + " { ";
10330
+ let checkBlock = "";
9710
10331
  if (p.check) {
9711
- line += 'check "' + escapeString(p.check) + '" ';
10332
+ if (p.checkBound) {
10333
+ checkBlock = dumpExpressionBlock("check", p.check, " ");
10334
+ } else {
10335
+ line += 'check "' + escapeString(p.check) + '" ';
10336
+ }
9712
10337
  }
9713
10338
  if (p.description) {
9714
10339
  line += 'description "' + escapeString(p.description) + '" ';
@@ -9717,7 +10342,11 @@ var dumpConformanceTest = function(ct) {
9717
10342
  if (p.onUnresolvable) {
9718
10343
  line += "on_unresolvable " + p.onUnresolvable + " ";
9719
10344
  }
9720
- out += line + "}\n";
10345
+ if (checkBlock) {
10346
+ out += line + "\n" + checkBlock + " }\n";
10347
+ } else {
10348
+ out += line + "}\n";
10349
+ }
9721
10350
  }
9722
10351
  out += " }\n";
9723
10352
  }
@@ -10082,7 +10711,9 @@ var parseVerdict = function(id, data) {
10082
10711
  } else if (keyword === "behavior") {
10083
10712
  result.behavior = value();
10084
10713
  } else if (keyword === "derive" || keyword === "expression") {
10085
- result.derive = unwrapped(value);
10714
+ const c = readExpressionCarrier(value(), "verdict derive");
10715
+ result.derive = c.source;
10716
+ result.deriveBound = c.inline || void 0;
10086
10717
  } else if (keyword === "inputs" || keyword === "uses") {
10087
10718
  result.inputs = readIdList3(value());
10088
10719
  } else if (keyword === "series_reduction") {
@@ -10140,7 +10771,11 @@ var dumpVerdict = function(v) {
10140
10771
  out += " }\n";
10141
10772
  }
10142
10773
  if (v.derive) {
10143
- out += ' derive "' + escapeString(v.derive) + '"\n';
10774
+ if (v.deriveBound) {
10775
+ out += dumpExpressionBlock("derive", v.derive, " ");
10776
+ } else {
10777
+ out += ' derive "' + escapeString(v.derive) + '"\n';
10778
+ }
10144
10779
  }
10145
10780
  if (v.inputs.length > 0) {
10146
10781
  out += " inputs { " + v.inputs.join(" ") + " }\n";
@@ -10743,8 +11378,15 @@ var parseConstraint = function(id, data) {
10743
11378
  result.stereotype = stripWrapping(t[i++]);
10744
11379
  } else if (keyword === "name") {
10745
11380
  result.name = readValue2(t[i++]);
11381
+ } else if (keyword === "args") {
11382
+ if (!result.args) {
11383
+ result.args = [];
11384
+ }
11385
+ result.args.push(...readArgsBlock(unwrapBlock(t[i++])));
10746
11386
  } else if (keyword === "check") {
10747
- result.check = readValue2(t[i++]);
11387
+ const c = readExpressionCarrier(t[i++], "constraint check");
11388
+ result.check = c.source;
11389
+ result.checkBound = c.inline || void 0;
10748
11390
  } else if (keyword === "violation_meaning") {
10749
11391
  result.violationMeaning = readValue2(t[i++]);
10750
11392
  } else if (keyword === "on_violation") {
@@ -10778,8 +11420,19 @@ var dumpConstraint = function(c) {
10778
11420
  if (c.name) {
10779
11421
  out += ' name "' + escapeString(c.name) + '"\n';
10780
11422
  }
11423
+ if ((c.args ?? []).length > 0) {
11424
+ out += " args {\n";
11425
+ for (const a of c.args ?? []) {
11426
+ out += " " + a.name + " <- " + a.source + "\n";
11427
+ }
11428
+ out += " }\n";
11429
+ }
10781
11430
  if (c.check) {
10782
- out += ' check "' + escapeString(c.check) + '"\n';
11431
+ if (c.checkBound) {
11432
+ out += dumpExpressionBlock("check", c.check, " ");
11433
+ } else {
11434
+ out += ' check "' + escapeString(c.check) + '"\n';
11435
+ }
10783
11436
  }
10784
11437
  if (c.violationMeaning) {
10785
11438
  out += ' violation_meaning "' + escapeString(c.violationMeaning) + '"\n';
@@ -10798,6 +11451,169 @@ var dumpConstraint = function(c) {
10798
11451
  return out;
10799
11452
  };
10800
11453
 
11454
+ // src/ser-des/config/uncertaintyBudget.ts
11455
+ var DISTRIBUTIONS = /* @__PURE__ */ new Set([
11456
+ "rectangular",
11457
+ "triangular",
11458
+ "normal",
11459
+ "ushape"
11460
+ ]);
11461
+ function readComponent(block) {
11462
+ const c = {
11463
+ id: "",
11464
+ type: "B",
11465
+ series: "",
11466
+ distribution: "",
11467
+ halfWidth: "",
11468
+ unit: "",
11469
+ source: null,
11470
+ description: ""
11471
+ };
11472
+ const t = tokenizePackage(block);
11473
+ let i = 0;
11474
+ while (i < t.length) {
11475
+ const kw = t[i++];
11476
+ if (i >= t.length) {
11477
+ throw new Error(
11478
+ `Parsing error: uncertainty_budget component. ID ${c.id}: Expecting value for ${kw}`
11479
+ );
11480
+ }
11481
+ if (kw === "type") {
11482
+ const v = stripWrapping(t[i++]);
11483
+ if (v !== "A" && v !== "B") {
11484
+ throw new Error(
11485
+ `Parsing error: uncertainty_budget component. ID ${c.id}: unknown type "${v}" (A evaluates the statistics of a series; B states a distribution)`
11486
+ );
11487
+ }
11488
+ c.type = v;
11489
+ } else if (kw === "series") {
11490
+ c.series = stripWrapping(t[i++]);
11491
+ } else if (kw === "distribution") {
11492
+ const v = stripWrapping(t[i++]);
11493
+ if (!DISTRIBUTIONS.has(v)) {
11494
+ throw new Error(
11495
+ `Parsing error: uncertainty_budget component. ID ${c.id}: unknown distribution "${v}" (rectangular | triangular | normal | ushape)`
11496
+ );
11497
+ }
11498
+ c.distribution = v;
11499
+ } else if (kw === "half_width") {
11500
+ c.halfWidth = stripWrapping(t[i++]);
11501
+ } else if (kw === "unit") {
11502
+ c.unit = stripWrapping(t[i++]);
11503
+ } else if (kw === "description") {
11504
+ c.description = stripWrapping(t[i++]);
11505
+ } else if (kw === "source") {
11506
+ c.source = readSource(unwrapBlock(t[i++]));
11507
+ } else {
11508
+ i = skipUnknownValue(t, i, kw);
11509
+ }
11510
+ }
11511
+ return c;
11512
+ }
11513
+ var parseUncertaintyBudget = function(id, data) {
11514
+ const result = {
11515
+ id,
11516
+ target: "",
11517
+ coverageK: "",
11518
+ components: [],
11519
+ source: null
11520
+ };
11521
+ const t = tokenizePackage(data);
11522
+ let i = 0;
11523
+ while (i < t.length) {
11524
+ const kw = t[i++];
11525
+ if (i >= t.length) {
11526
+ throw new Error(
11527
+ `Parsing error: uncertainty_budget. ID ${id}: Expecting value for ${kw}`
11528
+ );
11529
+ }
11530
+ if (kw === "target") {
11531
+ result.target = stripWrapping(t[i++]);
11532
+ } else if (kw === "coverage") {
11533
+ const head = stripWrapping(t[i++]);
11534
+ if (head !== "k") {
11535
+ throw new Error(
11536
+ `Parsing error: uncertainty_budget. ID ${id}: coverage states its factor \u2014 coverage k <number>`
11537
+ );
11538
+ }
11539
+ result.coverageK = stripWrapping(t[i++]);
11540
+ } else if (kw === "component") {
11541
+ if (t[i].startsWith("{")) {
11542
+ throw new Error(
11543
+ `Parsing error: uncertainty_budget. ID ${id}: a component carries an id \u2014 component <id> { \u2026 }`
11544
+ );
11545
+ }
11546
+ const cid = stripWrapping(t[i++]);
11547
+ const c = readComponent(unwrapBlock(t[i++]));
11548
+ c.id = cid;
11549
+ result.components.push(c);
11550
+ } else if (kw === "source") {
11551
+ result.source = readSource(unwrapBlock(t[i++]));
11552
+ } else if (kw === "ref") {
11553
+ const rr = parseRef(t, i, stripWrapping, unwrapBlock);
11554
+ if (!foldRefIntoLegacy(result, rr.ref)) {
11555
+ (result.refs ??= []).push(rr.ref);
11556
+ }
11557
+ i = rr.next;
11558
+ } else if (kw === "corresponds") {
11559
+ const cc = parseCorresponds(t, i, stripWrapping);
11560
+ (result.correspondences ??= []).push(cc.corr);
11561
+ i = cc.next;
11562
+ } else {
11563
+ i = skipUnknownValue(t, i, kw);
11564
+ }
11565
+ }
11566
+ return (ctx) => {
11567
+ ctx.uncertaintyBudgets[id] = result;
11568
+ return ctx;
11569
+ };
11570
+ };
11571
+ var dumpUncertaintyBudget = function(b) {
11572
+ let out = "uncertainty_budget " + b.id + " {\n";
11573
+ if (b.target) {
11574
+ out += " target " + b.target + "\n";
11575
+ }
11576
+ if (b.coverageK) {
11577
+ out += " coverage k " + b.coverageK + "\n";
11578
+ }
11579
+ for (const c of b.components) {
11580
+ out += " component " + c.id + " {\n";
11581
+ out += " type " + c.type + "\n";
11582
+ if (c.type === "A" && c.series) {
11583
+ out += " series " + c.series + "\n";
11584
+ }
11585
+ if (c.type === "B") {
11586
+ if (c.distribution) {
11587
+ out += " distribution " + c.distribution + "\n";
11588
+ }
11589
+ if (c.halfWidth) {
11590
+ out += " half_width " + c.halfWidth + "\n";
11591
+ }
11592
+ if (c.unit) {
11593
+ out += ' unit "' + escapeString(c.unit) + '"\n';
11594
+ }
11595
+ }
11596
+ if (c.description) {
11597
+ out += ' description "' + escapeString(c.description) + '"\n';
11598
+ }
11599
+ if (c.source && (c.source.doc || c.source.clause)) {
11600
+ out += ' source { doc "' + escapeString(c.source.doc) + '" clause "' + escapeString(c.source.clause) + '"' + (c.source.fragment ? ' fragment "' + escapeString(c.source.fragment) + '"' : "") + " }\n";
11601
+ }
11602
+ out += " }\n";
11603
+ }
11604
+ if (b.source && (b.source.doc || b.source.clause)) {
11605
+ out += ' source { doc "' + escapeString(b.source.doc) + '" clause "' + escapeString(b.source.clause) + '"' + (b.source.fragment ? ' fragment "' + escapeString(b.source.fragment) + '"' : "") + " }\n";
11606
+ }
11607
+ out += dumpCorrespondences(
11608
+ b.correspondences,
11609
+ " ",
11610
+ escapeString,
11611
+ dumpBareSafe
11612
+ );
11613
+ out += "}\n";
11614
+ return out;
11615
+ };
11616
+
10801
11617
  // src/ser-des/config/discrepancyRecord.ts
10802
11618
  var VALID_STATUSES = ["open", "resolved"];
10803
11619
  var parseDiscrepancyRecord = function(id, data) {
@@ -11146,8 +11962,8 @@ function readAccepts(block) {
11146
11962
  }
11147
11963
  return accepts;
11148
11964
  }
11149
- function readLimit(block) {
11150
- const limit = {
11965
+ function blankLimit() {
11966
+ return {
11151
11967
  expression: "",
11152
11968
  uses: [],
11153
11969
  modality: "",
@@ -11158,15 +11974,51 @@ function readLimit(block) {
11158
11974
  acceptance: null,
11159
11975
  sourceDiscrepancy: null
11160
11976
  };
11161
- const t = tokenize(block);
11162
- let i = 0;
11977
+ }
11978
+ function readLimit(block) {
11979
+ const limit = blankLimit();
11980
+ readLegacyLimitFields(tokenize(block), limit, 0);
11981
+ return limit;
11982
+ }
11983
+ function readExpressionBlock(raw) {
11984
+ return canonicalizeExpression(raw);
11985
+ }
11986
+ function readLegacyLimitFields(t, limit, start) {
11987
+ let i = start;
11163
11988
  while (i < t.length) {
11164
11989
  const cmd = t[i++];
11165
11990
  if (i >= t.length) {
11166
11991
  break;
11167
11992
  }
11168
- if (cmd === "expression") {
11169
- limit.expression = stripWrapping(t[i++]);
11993
+ if (cmd === "args") {
11994
+ if (!limit.args) {
11995
+ limit.args = [];
11996
+ }
11997
+ const at = tokenize(unwrapBlock(t[i++]));
11998
+ let k = 0;
11999
+ while (k < at.length) {
12000
+ const name = stripWrapping(at[k++]);
12001
+ const arrow = at[k];
12002
+ if (arrow !== "<-") {
12003
+ throw new Error(
12004
+ `limit args: expected "<-" after "${name}" (name <- source)`
12005
+ );
12006
+ }
12007
+ k += 1;
12008
+ if (k >= at.length) {
12009
+ throw new Error(`limit args: "${name}" binds to nothing`);
12010
+ }
12011
+ const source = stripWrapping(at[k++]);
12012
+ limit.args.push({ name, source });
12013
+ }
12014
+ } else if (cmd === "expression") {
12015
+ const value = t[i++];
12016
+ if (value.startsWith("{")) {
12017
+ limit.argsBound = true;
12018
+ limit.expression = readExpressionBlock(unwrapBlock(value));
12019
+ } else {
12020
+ limit.expression = stripWrapping(value);
12021
+ }
11170
12022
  } else if (cmd === "uses") {
11171
12023
  limit.uses = readIdList4(t[i++]);
11172
12024
  } else if (cmd === "modality") {
@@ -11203,7 +12055,6 @@ function readLimit(block) {
11203
12055
  i = skipUnknownValue(t, i, cmd);
11204
12056
  }
11205
12057
  }
11206
- return limit;
11207
12058
  }
11208
12059
  function readSubjects(block) {
11209
12060
  const out = [];
@@ -11415,6 +12266,52 @@ var parseRequirement = function(id, data) {
11415
12266
  };
11416
12267
  };
11417
12268
  function dumpLimit(limit) {
12269
+ if (limit.argsBound) {
12270
+ let out2 = " limit {\n";
12271
+ if ((limit.args ?? []).length > 0) {
12272
+ out2 += " args {\n";
12273
+ for (const a of limit.args ?? []) {
12274
+ out2 += " " + a.name + " <- " + a.source + "\n";
12275
+ }
12276
+ out2 += " }\n";
12277
+ }
12278
+ out2 += " expression {\n";
12279
+ for (const line of limit.expression.split("\n")) {
12280
+ out2 += " " + line + "\n";
12281
+ }
12282
+ out2 += " }\n";
12283
+ if (limit.modality) {
12284
+ out2 += " modality " + limit.modality + "\n";
12285
+ }
12286
+ if (limit.relativeTo) {
12287
+ out2 += " relative_to " + limit.relativeTo + "\n";
12288
+ }
12289
+ if (limit.notes) {
12290
+ out2 += ' notes "' + escapeString(limit.notes) + '"\n';
12291
+ }
12292
+ if (limit.accepts) {
12293
+ const a = limit.accepts;
12294
+ let line = " accepts { verdict " + a.verdict;
12295
+ if (a.op) {
12296
+ line += " op " + a.op;
12297
+ }
12298
+ if (a.limit) {
12299
+ line += ' limit "' + escapeString(a.limit) + '"';
12300
+ }
12301
+ if (a.sourceDiscrepancy) {
12302
+ line += " " + dumpSourceDiscrepancy(a.sourceDiscrepancy, "");
12303
+ }
12304
+ out2 += line + " }\n";
12305
+ }
12306
+ if (limit.acceptance) {
12307
+ out2 += dumpAcceptance(limit.acceptance, " ") + "\n";
12308
+ }
12309
+ if (limit.sourceDiscrepancy) {
12310
+ out2 += dumpSourceDiscrepancy(limit.sourceDiscrepancy, " ") + "\n";
12311
+ }
12312
+ out2 += " }\n";
12313
+ return out2;
12314
+ }
11418
12315
  let out = " limit {\n";
11419
12316
  if (limit.expression) {
11420
12317
  out += ' expression "' + escapeString(limit.expression) + '"\n';
@@ -11578,8 +12475,12 @@ var parseRequirementClass = function(id, data) {
11578
12475
  subject: "",
11579
12476
  guidance: "",
11580
12477
  dependencies: [],
11581
- referenceIds: []
12478
+ referenceIds: [],
12479
+ limit: null,
12480
+ members: []
11582
12481
  };
12482
+ const nestedParsers = [];
12483
+ const members = [];
11583
12484
  const t = tokenizePackage(data);
11584
12485
  let i = 0;
11585
12486
  while (i < t.length) {
@@ -11603,11 +12504,24 @@ var parseRequirementClass = function(id, data) {
11603
12504
  result.dependencies = readIdList4(t[i++]);
11604
12505
  } else if (cmd === "reference") {
11605
12506
  result.referenceIds = readIdList4(t[i++]);
12507
+ } else if (cmd === "limit") {
12508
+ result.limit = readLimit(unwrapBlock(t[i++]));
12509
+ } else if (cmd === "requirement") {
12510
+ const childId = stripWrapping(t[i++]);
12511
+ const childBlock = t[i++];
12512
+ const childParse = parseRequirement(childId, unwrapBlock(childBlock));
12513
+ nestedParsers.push(childParse);
12514
+ members.push(childId);
11606
12515
  } else {
11607
12516
  i = skipUnknownValue(t, i, cmd);
11608
12517
  }
11609
12518
  }
11610
12519
  return (ctx) => {
12520
+ const c = ctx;
12521
+ for (const parse2 of nestedParsers) {
12522
+ parse2(c);
12523
+ }
12524
+ result.members = members;
11611
12525
  ctx.requirementClasses[id] = result;
11612
12526
  return ctx;
11613
12527
  };
@@ -11632,6 +12546,9 @@ var dumpRequirementClass = function(rc) {
11632
12546
  if (rc.referenceIds.length > 0) {
11633
12547
  out += " reference { " + rc.referenceIds.join(" ") + " }\n";
11634
12548
  }
12549
+ if (rc.limit) {
12550
+ out += dumpLimit(rc.limit);
12551
+ }
11635
12552
  out += "}\n";
11636
12553
  return out;
11637
12554
  };
@@ -11700,6 +12617,8 @@ var parsePackage = function(data) {
11700
12617
  manifest.title = stripWrapping(t[i++]);
11701
12618
  } else if (cmd === "version") {
11702
12619
  manifest.version = stripWrapping(t[i++]);
12620
+ } else if (cmd === "language") {
12621
+ manifest.language = stripWrapping(t[i++]);
11703
12622
  } else if (cmd === "editions") {
11704
12623
  manifest.editions = readList(t[i++]);
11705
12624
  } else if (cmd === "baseUrn" || cmd === "base_urn") {
@@ -18912,6 +19831,298 @@ var dumpPartAnnex = function(a) {
18912
19831
  return out;
18913
19832
  };
18914
19833
 
19834
+ // src/ser-des/config/lmlAligned.ts
19835
+ var MATH_NOTATIONS = ["asciimath", "latex", "unicodemath", "mathml", "omml"];
19836
+ var MAPPING_FORMATS = ["xml", "yaml", "json", "toml", "csv"];
19837
+ function splitMappingId(id) {
19838
+ const at = id.indexOf(":");
19839
+ const format = at === -1 ? "xml" : id.slice(0, at);
19840
+ return { format, target: at === -1 ? id : id.slice(at + 1) };
19841
+ }
19842
+ var parseWireMapping = function(id, data) {
19843
+ const { format, target } = splitMappingId(id);
19844
+ const out = {
19845
+ id,
19846
+ format,
19847
+ target,
19848
+ element: "",
19849
+ namespaceRef: "",
19850
+ content: "",
19851
+ mixed: false,
19852
+ renderNil: null,
19853
+ entries: [],
19854
+ source: null
19855
+ };
19856
+ forEachEntry(
19857
+ data,
19858
+ (command, value, peek) => {
19859
+ if (command === "element") {
19860
+ out.element = stripWrapping(value());
19861
+ } else if (command === "namespace") {
19862
+ out.namespaceRef = stripWrapping(value());
19863
+ } else if (command === "mixed_content") {
19864
+ value();
19865
+ out.mixed = true;
19866
+ } else if (command === "render_nil") {
19867
+ out.renderNil = stripWrapping(value()) === "true";
19868
+ } else if (command === "map_content") {
19869
+ out.content = stripWrapping(value());
19870
+ } else if (command === "map_element" || command === "map_attribute" || command === "map") {
19871
+ const wire = stripWrapping(value());
19872
+ const name = peek() !== void 0 ? stripWrapping(value()) : "";
19873
+ const kind = command === "map_element" ? "element" : command === "map_attribute" ? "attribute" : "map";
19874
+ out.entries.push({ kind, wire, name, modifier: "" });
19875
+ } else if (command === "map_key" || command === "map_value") {
19876
+ const modifier = stripWrapping(value());
19877
+ const name = peek() !== void 0 ? stripWrapping(value()) : "";
19878
+ out.entries.push({ kind: "map", wire: command, name, modifier });
19879
+ } else {
19880
+ return false;
19881
+ }
19882
+ return true;
19883
+ },
19884
+ { construct: "mapping", id }
19885
+ );
19886
+ return (ctx) => {
19887
+ ctx.wireMappings[id] = out;
19888
+ return ctx;
19889
+ };
19890
+ };
19891
+ var dumpWireMapping = function(w) {
19892
+ const lines = [`mapping ${w.format} ${w.target} {`];
19893
+ if (w.element) {
19894
+ lines.push(` element "${escapeString(w.element)}"`);
19895
+ }
19896
+ if (w.namespaceRef) {
19897
+ lines.push(` namespace ${w.namespaceRef}`);
19898
+ }
19899
+ for (const e of w.entries) {
19900
+ if (e.kind === "map" && e.modifier) {
19901
+ lines.push(` ${e.wire} ${e.modifier} ${e.name}`);
19902
+ } else {
19903
+ const kw = e.kind === "element" ? "map_element" : e.kind === "attribute" ? "map_attribute" : "map";
19904
+ lines.push(` ${kw} "${escapeString(e.wire)}" ${e.name}`);
19905
+ }
19906
+ }
19907
+ if (w.content) {
19908
+ lines.push(` map_content ${w.content}`);
19909
+ }
19910
+ if (w.mixed) {
19911
+ lines.push(` mixed_content`);
19912
+ }
19913
+ if (w.renderNil !== null) {
19914
+ lines.push(` render_nil ${w.renderNil}`);
19915
+ }
19916
+ lines.push("}");
19917
+ return lines.join("\n");
19918
+ };
19919
+ var parseStringFormat = function(rawId, data) {
19920
+ if (!rawId.startsWith(":")) {
19921
+ throw new Error(
19922
+ `Parsing error: string_format. ID ${rawId}: the registered format name carries the colon sigil (string_format :${rawId})`
19923
+ );
19924
+ }
19925
+ const id = rawId.slice(1);
19926
+ const out = { id, artifact: "", root: "", source: null };
19927
+ forEachEntry(
19928
+ data,
19929
+ (command, value) => {
19930
+ if (command === "artifact") {
19931
+ out.artifact = stripWrapping(value());
19932
+ } else if (command === "root") {
19933
+ out.root = stripWrapping(value());
19934
+ } else {
19935
+ return false;
19936
+ }
19937
+ return true;
19938
+ },
19939
+ { construct: "string_format", id }
19940
+ );
19941
+ return (ctx) => {
19942
+ ctx.stringFormats[id] = out;
19943
+ return ctx;
19944
+ };
19945
+ };
19946
+ var dumpStringFormat = function(f) {
19947
+ return [
19948
+ `string_format :${f.id} {`,
19949
+ ` artifact "${escapeString(f.artifact)}"`,
19950
+ ` root "${escapeString(f.root)}"`,
19951
+ "}"
19952
+ ].join("\n");
19953
+ };
19954
+ var parseNamespace = function(id, data) {
19955
+ const out = {
19956
+ id,
19957
+ uri: "",
19958
+ prefix: "",
19959
+ isDefault: false,
19960
+ source: null
19961
+ };
19962
+ forEachEntry(
19963
+ data,
19964
+ (command, value) => {
19965
+ if (command === "uri") {
19966
+ out.uri = stripWrapping(value());
19967
+ } else if (command === "prefix") {
19968
+ out.prefix = stripWrapping(value());
19969
+ } else if (command === "default") {
19970
+ value();
19971
+ out.isDefault = true;
19972
+ } else {
19973
+ return false;
19974
+ }
19975
+ return true;
19976
+ },
19977
+ { construct: "namespace", id }
19978
+ );
19979
+ return (ctx) => {
19980
+ ctx.namespaces[id] = out;
19981
+ return ctx;
19982
+ };
19983
+ };
19984
+ var dumpNamespace = function(d) {
19985
+ const lines = [`namespace ${d.id} {`, ` uri "${escapeString(d.uri)}"`];
19986
+ if (d.prefix) {
19987
+ lines.push(` prefix "${escapeString(d.prefix)}"`);
19988
+ }
19989
+ if (d.isDefault) {
19990
+ lines.push(` default`);
19991
+ }
19992
+ lines.push("}");
19993
+ return lines.join("\n");
19994
+ };
19995
+ var parseDatum = function(id, raw) {
19996
+ const data = raw.replace(/^\s*:\s*\S+\s*/, "");
19997
+ const out = {
19998
+ id,
19999
+ type: "",
20000
+ unit: "",
20001
+ quantityKind: "",
20002
+ origin: "declared",
20003
+ scope: "",
20004
+ renders: [],
20005
+ label: "",
20006
+ description: "",
20007
+ source: null
20008
+ };
20009
+ forEachEntry(
20010
+ data,
20011
+ (command, value, peek) => {
20012
+ if (command === "render") {
20013
+ const notation = stripWrapping(value());
20014
+ const text = peek() !== void 0 ? stripWrapping(value()) : "";
20015
+ if (MATH_NOTATIONS.includes(notation)) {
20016
+ out.renders.push({ notation, text });
20017
+ }
20018
+ } else if (command === "label") {
20019
+ out.label = stripWrapping(value());
20020
+ } else if (command === "description") {
20021
+ const v = value();
20022
+ out.description = v.startsWith("{") ? unwrapBlock(v) : stripWrapping(v);
20023
+ } else if (command === "unit") {
20024
+ out.unit = stripWrapping(value());
20025
+ } else if (command === "quantity_kind") {
20026
+ out.quantityKind = stripWrapping(value());
20027
+ } else if (command === "origin") {
20028
+ const o = stripWrapping(value());
20029
+ if (["declared", "design-fixed", "observed", "computed"].includes(o)) {
20030
+ out.origin = o;
20031
+ }
20032
+ } else if (command === "scope") {
20033
+ out.scope = stripWrapping(value());
20034
+ } else {
20035
+ return false;
20036
+ }
20037
+ return true;
20038
+ },
20039
+ { construct: "datum", id }
20040
+ );
20041
+ return (ctx) => {
20042
+ ctx.datums[id] = out;
20043
+ return ctx;
20044
+ };
20045
+ };
20046
+ var dumpDatum = function(x) {
20047
+ const lines = [`datum ${x.id}${x.type ? ` : ${x.type}` : ""} {`];
20048
+ if (x.quantityKind) {
20049
+ lines.push(` quantity_kind ${x.quantityKind}`);
20050
+ }
20051
+ if (x.unit) {
20052
+ lines.push(` unit ${x.unit}`);
20053
+ }
20054
+ if (x.origin !== "declared") {
20055
+ lines.push(` origin ${x.origin}`);
20056
+ }
20057
+ if (x.scope) {
20058
+ lines.push(` scope ${x.scope}`);
20059
+ }
20060
+ for (const r of x.renders) {
20061
+ lines.push(` render ${r.notation} "${escapeString(r.text)}"`);
20062
+ }
20063
+ if (x.label) {
20064
+ lines.push(` label "${escapeString(x.label)}"`);
20065
+ }
20066
+ if (x.description) {
20067
+ lines.push(` description { ${x.description} }`);
20068
+ }
20069
+ lines.push("}");
20070
+ return lines.join("\n");
20071
+ };
20072
+ var parseCheck = function(id, data) {
20073
+ const out = {
20074
+ id,
20075
+ inputs: [],
20076
+ expression: "",
20077
+ operator: "",
20078
+ threshold: "",
20079
+ source: null
20080
+ };
20081
+ forEachEntry(
20082
+ data,
20083
+ (command, value, peek) => {
20084
+ if (command === "inputs") {
20085
+ const block = value();
20086
+ const inner = block.startsWith("{") ? tokenizePackage(unwrapBlock(block)) : [];
20087
+ out.inputs = inner.map((x) => stripWrapping(x));
20088
+ } else if (command === "expression") {
20089
+ out.expression = stripWrapping(value());
20090
+ } else if (command === "operator") {
20091
+ out.operator = stripWrapping(value());
20092
+ } else if (command === "threshold") {
20093
+ const v = value();
20094
+ out.threshold = v.startsWith("{") ? unwrapBlock(v) : stripWrapping(v);
20095
+ } else {
20096
+ return false;
20097
+ }
20098
+ void peek;
20099
+ return true;
20100
+ },
20101
+ { construct: "check", id }
20102
+ );
20103
+ return (ctx) => {
20104
+ ctx.checks[id] = out;
20105
+ return ctx;
20106
+ };
20107
+ };
20108
+ var dumpCheck = function(x) {
20109
+ const lines = [`check ${x.id} {`];
20110
+ if (x.inputs.length) {
20111
+ lines.push(` inputs { ${x.inputs.join(" ")} }`);
20112
+ }
20113
+ if (x.expression) {
20114
+ lines.push(` expression "${escapeString(x.expression)}"`);
20115
+ }
20116
+ if (x.operator) {
20117
+ lines.push(` operator ${x.operator}`);
20118
+ }
20119
+ if (x.threshold) {
20120
+ lines.push(` threshold ${x.threshold}`);
20121
+ }
20122
+ lines.push("}");
20123
+ return lines.join("\n");
20124
+ };
20125
+
18915
20126
  // src/ser-des/config/index.ts
18916
20127
  function defineConstruct(def) {
18917
20128
  return def;
@@ -19287,6 +20498,14 @@ var CONSTRUCTS = [
19287
20498
  parse: parseConstraint,
19288
20499
  dump: dumpConstraint
19289
20500
  }),
20501
+ // The uncertainty budgets (register W5 — the GUM plane's language side)
20502
+ defineConstruct({
20503
+ keyword: "uncertainty_budget",
20504
+ field: "uncertaintyBudgets",
20505
+ takesID: true,
20506
+ parse: parseUncertaintyBudget,
20507
+ dump: dumpUncertaintyBudget
20508
+ }),
19290
20509
  // Corpus-level source-discrepancy records (TODO.roadmap/54 — gap 13's
19291
20510
  // corpus-level extension of the source_discrepancy facet)
19292
20511
  defineConstruct({
@@ -19575,7 +20794,45 @@ var CONSTRUCTS = [
19575
20794
  // Primmel v3.2 consumption constructs (TODO.primmel/11; MN 114 clause
19576
20795
  // 10.6): the top-level applicability dimension (one grammar with the
19577
20796
  // instrument's inline dimension blocks, two placements).
19578
- dimensionConstruct
20797
+ dimensionConstruct,
20798
+ // ── the LML-aligned substrate (TODO.lang-gaps; Annex F) ─────────
20799
+ defineConstruct({
20800
+ keyword: "mapping",
20801
+ field: "wireMappings",
20802
+ takesID: true,
20803
+ takesFormat: true,
20804
+ parse: parseWireMapping,
20805
+ dump: dumpWireMapping
20806
+ }),
20807
+ defineConstruct({
20808
+ keyword: "string_format",
20809
+ field: "stringFormats",
20810
+ takesID: true,
20811
+ parse: parseStringFormat,
20812
+ dump: dumpStringFormat
20813
+ }),
20814
+ defineConstruct({
20815
+ keyword: "namespace",
20816
+ field: "namespaces",
20817
+ takesID: true,
20818
+ parse: parseNamespace,
20819
+ dump: dumpNamespace
20820
+ }),
20821
+ defineConstruct({
20822
+ keyword: "datum",
20823
+ field: "datums",
20824
+ takesID: true,
20825
+ optionalTypedId: true,
20826
+ parse: parseDatum,
20827
+ dump: dumpDatum
20828
+ }),
20829
+ defineConstruct({
20830
+ keyword: "check",
20831
+ field: "checks",
20832
+ takesID: true,
20833
+ parse: parseCheck,
20834
+ dump: dumpCheck
20835
+ })
19579
20836
  ];
19580
20837
  function buildParserConfig(constructs) {
19581
20838
  const out = {};
@@ -19585,6 +20842,8 @@ function buildParserConfig(constructs) {
19585
20842
  }
19586
20843
  const entry = {
19587
20844
  takesID: c.takesID,
20845
+ takesFormat: c.takesFormat,
20846
+ optionalTypedId: c.optionalTypedId,
19588
20847
  parse: c.parse,
19589
20848
  field: c.field,
19590
20849
  ...c.deprecated ? { deprecated: c.deprecated } : {}
@@ -19811,6 +21070,9 @@ function loadPackageInternal(dir, options = {}, withProvenance = false) {
19811
21070
  return composePackage(dir, options, manifest, withProvenance);
19812
21071
  }
19813
21072
  const parseOptions = withProvenance ? { ...options, withProvenance: true } : options;
21073
+ if (manifest?.language) {
21074
+ parseOptions.strict = true;
21075
+ }
19814
21076
  const ctx = parse(joinChunks(chunks), PARSER_CONFIG, parseOptions);
19815
21077
  if (manifest) {
19816
21078
  ctx.packageManifest = manifest;
@@ -19894,6 +21156,11 @@ var MERGE_FIELDS = [
19894
21156
  "calculations",
19895
21157
  "verdicts",
19896
21158
  "referenceMaterials",
21159
+ "wireMappings",
21160
+ "stringFormats",
21161
+ "namespaces",
21162
+ "datums",
21163
+ "checks",
19897
21164
  "testPointSets",
19898
21165
  "commonTestConditions",
19899
21166
  "competenceKinds",
@@ -19903,6 +21170,7 @@ var MERGE_FIELDS = [
19903
21170
  "schemeActivityKinds",
19904
21171
  "schemeTypes",
19905
21172
  "constraints",
21173
+ "uncertaintyBudgets",
19906
21174
  "discrepancyRecords",
19907
21175
  "stateMachines",
19908
21176
  "conformanceTests",
@@ -20134,7 +21402,12 @@ function composePackage(rootDir, options, rootManifest, withProvenance = false)
20134
21402
  const ctxs = /* @__PURE__ */ new Map();
20135
21403
  const pkgChunks = /* @__PURE__ */ new Map();
20136
21404
  for (const id of order) {
20137
- const parsed = parsePackageContent(dirs.get(id), parseOptions);
21405
+ const pkgOptions = { ...parseOptions };
21406
+ const pkgManifest = manifests.get(id);
21407
+ if (pkgManifest?.language) {
21408
+ pkgOptions.strict = true;
21409
+ }
21410
+ const parsed = parsePackageContent(dirs.get(id), pkgOptions);
20138
21411
  ctxs.set(id, parsed.ctx);
20139
21412
  pkgChunks.set(id, parsed.chunks);
20140
21413
  }
@@ -20233,7 +21506,21 @@ function composePackage(rootDir, options, rootManifest, withProvenance = false)
20233
21506
  for (const id of order) {
20234
21507
  const m = manifests.get(id);
20235
21508
  for (const req of m.requires ?? []) {
20236
- const satisfied = order.some(
21509
+ const at = req.indexOf(":");
21510
+ const scoped = at > 0 ? { pkg: req.slice(0, at), token: req.slice(at + 1) } : null;
21511
+ let scopedProvides = null;
21512
+ if (scoped && !order.includes(scoped.pkg)) {
21513
+ try {
21514
+ const dir = locate(scoped.pkg);
21515
+ if (dir) {
21516
+ const rm = readPackageManifest(dir);
21517
+ scopedProvides = rm.provides ?? [];
21518
+ manifests.set(scoped.pkg, rm);
21519
+ }
21520
+ } catch {
21521
+ }
21522
+ }
21523
+ const satisfied = scoped ? order.includes(scoped.pkg) ? (manifests.get(scoped.pkg).provides ?? []).includes(scoped.token) : (scopedProvides ?? []).includes(scoped.token) : order.some(
20237
21524
  (other) => other !== id && (other === req || (manifests.get(other).provides ?? []).includes(req))
20238
21525
  );
20239
21526
  if (!satisfied) {
@@ -22042,6 +23329,176 @@ var CHECK_RULES = [
22042
23329
  "normal",
22043
23330
  "the MMEL v2 validation parity (the rename contract \u2014 TODO.editor/41)"
22044
23331
  ),
23332
+ // ── the LML-aligned substrate (TODO.lang-gaps; the spec's validation
23333
+ // contract, language-v3 §16) ── The five constructs (mapping /
23334
+ // string_format / namespace / datum / check) carry their declared
23335
+ // data; the checker does the discipline. C163 is the release
23336
+ // classification contract — it runs over `primmel diff --exit-code`
23337
+ // (the existing diff classifier, src/model-diff.ts), so its catalog
23338
+ // entry documents the contract the CLI already enforces; no second
23339
+ // implementation lives here. C165/C166 are RESERVED for the
23340
+ // calculation math plane (the formula identifier bindings and the
23341
+ // Plurimath-conformant parse) — catalogued, not faked.
23342
+ R(
23343
+ "C158",
23344
+ "prose-quarantine",
23345
+ "base",
23346
+ "error",
23347
+ "normal",
23348
+ "the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
23349
+ ),
23350
+ R(
23351
+ "C159",
23352
+ "urn-only-refs",
23353
+ "base",
23354
+ "error",
23355
+ "normal",
23356
+ "the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
23357
+ ),
23358
+ R(
23359
+ "C160",
23360
+ "signature-closure",
23361
+ "base",
23362
+ "error",
23363
+ "normal",
23364
+ "the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
23365
+ ),
23366
+ R(
23367
+ "C161",
23368
+ "check-surface",
23369
+ "base",
23370
+ "error",
23371
+ "normal",
23372
+ "the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
23373
+ ),
23374
+ R(
23375
+ "C162",
23376
+ "namespace-coherence",
23377
+ "base",
23378
+ "error",
23379
+ "normal",
23380
+ "the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
23381
+ ),
23382
+ R(
23383
+ "C163",
23384
+ "change-levels",
23385
+ "base",
23386
+ "error",
23387
+ "normal",
23388
+ "the LML-aligned validation contract (language-v3 \xA716) \u2014 runs over `primmel diff --exit-code` (src/model-diff.ts, the diff classifier)"
23389
+ ),
23390
+ R(
23391
+ "C164",
23392
+ "wire-mapping-coverage",
23393
+ "base",
23394
+ "error",
23395
+ "normal",
23396
+ "the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
23397
+ ),
23398
+ R(
23399
+ "C165",
23400
+ "math-symbols-declared",
23401
+ "quantities",
23402
+ "warning",
23403
+ "normal",
23404
+ "RESERVED for the calculation math plane (language-v3 \xA716) \u2014 the formula identifier bindings"
23405
+ ),
23406
+ R(
23407
+ "C166",
23408
+ "math-parses",
23409
+ "quantities",
23410
+ "warning",
23411
+ "normal",
23412
+ "RESERVED for the calculation math plane (language-v3 \xA716) \u2014 the Plurimath-conformant parse (plurimath-ts)"
23413
+ ),
23414
+ R(
23415
+ "C167",
23416
+ "qualified-unit-reference",
23417
+ "quantities",
23418
+ "error",
23419
+ "normal",
23420
+ "the LML-aligned validation contract (language-v3 \xA716; TODO.lang-gaps)"
23421
+ ),
23422
+ R(
23423
+ "C168",
23424
+ "method-ref-resolves",
23425
+ "process",
23426
+ "error",
23427
+ "normal",
23428
+ "a conformance test method_ref names a process to be realized \u2014 bare in-package, or scoped <package>:<id> resolved read-only through the locator; never a bibliographic standard id"
23429
+ ),
23430
+ R(
23431
+ "C169",
23432
+ "provenance-clause-resolves",
23433
+ "base",
23434
+ "error",
23435
+ "normal",
23436
+ "a provenance binding citing a shipped document lands on a real fragment or sentence of that document \u2014 nothing linked to air"
23437
+ ),
23438
+ R(
23439
+ "C170",
23440
+ "edition-lineage-declared",
23441
+ "base",
23442
+ "error",
23443
+ "normal",
23444
+ "a package declaring more than one edition carries edition-mapping.json (primmel-edition-mapping/1) naming both edition states \u2014 the cross-edition linkage is an artifact, never implicit"
23445
+ ),
23446
+ R(
23447
+ "C171",
23448
+ "expression-identifiers-resolve",
23449
+ "base",
23450
+ "error",
23451
+ "normal",
23452
+ "every identifier inside a limit expression, derivation, or derive resolves to a declared name in scope \u2014 the formula is the executable core, nothing in it is air"
23453
+ ),
23454
+ R(
23455
+ "C172",
23456
+ "requirement-algebra-resolves",
23457
+ "base",
23458
+ "error",
23459
+ "normal",
23460
+ "containment is conjunction; a requirement class limit (the law) names its contained members with the OCL booleans \u2014 and/or/xor/implies \u2014 and every member appears in the law"
23461
+ ),
23462
+ R(
23463
+ "C176",
23464
+ "language-declared-wellformed",
23465
+ "base",
23466
+ "error",
23467
+ "normal",
23468
+ "a declared language generation is well-formed (v<major>[.<minor>]); the declaration makes the package parse strictly \u2014 unknown keywords are errors"
23469
+ ),
23470
+ R(
23471
+ "C179",
23472
+ "uncertainty-budget-resolves",
23473
+ "base",
23474
+ "error",
23475
+ "normal",
23476
+ "an uncertainty budget targets a declared verdict; a Type A component names a declared captured series, a Type B component states its distribution and half-width; the coverage factor is a positive number"
23477
+ ),
23478
+ R(
23479
+ "C173",
23480
+ "step-plane-refs-resolve",
23481
+ "process",
23482
+ "error",
23483
+ "normal",
23484
+ "a signature step's completion is one expression over the step's own declared ios; the calls bindings resolve the callee's declared signature; the dot-descent process:step.io resolves to a declared io"
23485
+ ),
23486
+ R(
23487
+ "C177",
23488
+ "kind-coherence",
23489
+ "base",
23490
+ "error",
23491
+ "normal",
23492
+ "a comparison in an inline expression sets operands of the same declared quantity kind \u2014 the kinds from the args' declared sources; unknown-kind and bare-number operands never conflict"
23493
+ ),
23494
+ R(
23495
+ "C178",
23496
+ "legacy-carrier-deprecated",
23497
+ "base",
23498
+ "warning",
23499
+ "normal",
23500
+ "a package declaring the deprecation generation carries quoted ocl{\u2026} expression carriers \u2014 the inline blocks (expression { \u2026 }, derive { \u2026 }, derivation { \u2026 }, check { \u2026 }) are the only forward form"
23501
+ ),
22045
23502
  // ── mapping (TODO.roadmap/04) ─────────────────────────────────────
22046
23503
  R(
22047
23504
  "C21",
@@ -23525,6 +24982,22 @@ var EMPTY = {
23525
24982
  textCoverageBudgetReason: null,
23526
24983
  entries: []
23527
24984
  };
24985
+ function issueElementId(message) {
24986
+ const m = message.match(/^[a-z_]+ ([^:\s][^:]*):/);
24987
+ return m ? m[1] : "";
24988
+ }
24989
+ function entryMatches(entry, issue) {
24990
+ if (issue.check !== entry.rule) {
24991
+ return false;
24992
+ }
24993
+ if (!globMatch(entry.match, issue.message)) {
24994
+ return false;
24995
+ }
24996
+ if (entry.id !== void 0) {
24997
+ return globMatch(entry.id, issueElementId(issue.message));
24998
+ }
24999
+ return true;
25000
+ }
23528
25001
  function globMatch(glob, text) {
23529
25002
  const re = new RegExp(
23530
25003
  "^" + glob.split("*").map(escapeRegExp).join("[\\s\\S]*") + "$"
@@ -23624,6 +25097,8 @@ function parseEntry2(block) {
23624
25097
  entry.rule = value;
23625
25098
  } else if (key === "match") {
23626
25099
  entry.match = value;
25100
+ } else if (key === "id") {
25101
+ entry.id = value;
23627
25102
  } else if (key === "reason") {
23628
25103
  entry.reason = value;
23629
25104
  } else if (key === "audit_ref") {
@@ -23642,6 +25117,13 @@ function validateEntry(entry) {
23642
25117
  message: `${ALLOWLIST_FILENAME}: entry${label} names ${entry.rule ? `unknown rule "${entry.rule}"` : "no rule"} \u2014 every allowlist entry names a real rule id (allowlist-malformed)`
23643
25118
  });
23644
25119
  }
25120
+ if (entry.id !== void 0 && entry.id === "") {
25121
+ issues.push({
25122
+ check: "C56",
25123
+ severity: "error",
25124
+ message: `${ALLOWLIST_FILENAME}: entry for rule "${entry.rule}" has an empty id glob \u2014 the structured key pins the element identity or is absent (allowlist-malformed)`
25125
+ });
25126
+ }
23645
25127
  if (!entry.match) {
23646
25128
  issues.push({
23647
25129
  check: "C56",
@@ -23677,7 +25159,7 @@ function applyAllowlist(issues, allowlist, activeRules) {
23677
25159
  }
23678
25160
  let matched = false;
23679
25161
  for (const issue of out) {
23680
- if (issue.check === entry.rule && globMatch(entry.match, issue.message)) {
25162
+ if (entryMatches(entry, issue)) {
23681
25163
  issue.known = true;
23682
25164
  matched = true;
23683
25165
  }
@@ -23742,7 +25224,7 @@ function applyProviderAllowlists(issues, providers, activeRules) {
23742
25224
  }
23743
25225
  let matched = false;
23744
25226
  for (const issue of out) {
23745
- if (!issue.known && issue.check === entry.rule && globMatch(entry.match, issue.message)) {
25227
+ if (!issue.known && entryMatches(entry, issue)) {
23746
25228
  issue.known = true;
23747
25229
  matched = true;
23748
25230
  }
@@ -24081,6 +25563,40 @@ function computeTextCoverage(standard, manifests, config) {
24081
25563
  }
24082
25564
  const documents = [];
24083
25565
  const matchedAllowanceSentences = /* @__PURE__ */ new Map();
25566
+ for (const manifest of manifests) {
25567
+ const urn = manifest.document.urn;
25568
+ const fragments = /* @__PURE__ */ new Set();
25569
+ const addresses = /* @__PURE__ */ new Set();
25570
+ for (const s of manifest.sentences) {
25571
+ fragments.add(s.fragment);
25572
+ addresses.add(s.address);
25573
+ }
25574
+ for (const b of bindings) {
25575
+ if (b.doc !== urn) {
25576
+ continue;
25577
+ }
25578
+ if (fragments.has(b.fragmentPath) || addresses.has(b.fragmentPath)) {
25579
+ continue;
25580
+ }
25581
+ const prefix = b.fragmentPath + ".";
25582
+ let resolved = false;
25583
+ for (const f of fragments) {
25584
+ if (f.startsWith(prefix) || b.fragmentPath.startsWith(f + "/")) {
25585
+ resolved = true;
25586
+ break;
25587
+ }
25588
+ }
25589
+ if (resolved) {
25590
+ continue;
25591
+ }
25592
+ const subpart = /^(table|figure|annex)-/.test(b.fragmentPath);
25593
+ configIssues.push({
25594
+ check: "C169",
25595
+ severity: subpart ? "warning" : "error",
25596
+ message: `provenance binding ${b.doc}#${b.fragmentPath} (${b.element}, ${b.kind}) names no fragment or sentence of the shipped document \u2014 ${subpart ? "a bare subpart citation the clause-only harvest cannot verify" : "linked to air"} (provenance-clause-resolves)`
25597
+ });
25598
+ }
25599
+ }
24084
25600
  for (const manifest of manifests) {
24085
25601
  const urn = manifest.document.urn;
24086
25602
  const sentences = manifest.sentences;
@@ -24479,6 +25995,7 @@ function checkPackage(dir, options = {}) {
24479
25995
  issues.push(...checkDimensions(standard));
24480
25996
  issues.push(...checkReferences(standard));
24481
25997
  issues.push(...checkVerdictChains(standard));
25998
+ issues.push(...checkLmlAligned(standard));
24482
25999
  issues.push(...checkClosedDerivations(standard));
24483
26000
  issues.push(...checkAttestations(standard));
24484
26001
  issues.push(...checkTypedPayloads(standard));
@@ -24563,9 +26080,12 @@ function checkPackage(dir, options = {}) {
24563
26080
  };
24564
26081
  (form.fields ?? []).forEach(checkField);
24565
26082
  }
26083
+ const classIds = new Set(
26084
+ (standard.requirementClasses ?? []).map((rc) => rc.id)
26085
+ );
24566
26086
  for (const t of standard.conformanceTests ?? []) {
24567
26087
  for (const target of t.targets ?? []) {
24568
- if (!reqIds.has(target)) {
26088
+ if (!reqIds.has(target) && !classIds.has(target)) {
24569
26089
  err(
24570
26090
  "C2",
24571
26091
  `conformance test ${t.id}: target "${target}" is not a declared requirement`
@@ -24722,9 +26242,19 @@ function checkPackage(dir, options = {}) {
24722
26242
  }
24723
26243
  }
24724
26244
  const covered = /* @__PURE__ */ new Set();
26245
+ const classMembers = /* @__PURE__ */ new Map();
26246
+ for (const rc of standard.requirementClasses ?? []) {
26247
+ classMembers.set(rc.id, rc.members ?? []);
26248
+ }
26249
+ const coverWithMembers = (id) => {
26250
+ covered.add(id);
26251
+ for (const m of classMembers.get(id) ?? []) {
26252
+ covered.add(m);
26253
+ }
26254
+ };
24725
26255
  for (const t of standard.conformanceTests ?? []) {
24726
26256
  for (const target of t.targets ?? []) {
24727
- covered.add(target);
26257
+ coverWithMembers(target);
24728
26258
  }
24729
26259
  }
24730
26260
  const provisioned = /* @__PURE__ */ new Set();
@@ -24763,6 +26293,989 @@ function checkPackage(dir, options = {}) {
24763
26293
  warn("C5", `conformance test ${t.id}: targets no requirement`);
24764
26294
  }
24765
26295
  }
26296
+ const OCL_WORDS = /* @__PURE__ */ new Set([
26297
+ "and",
26298
+ "or",
26299
+ "not",
26300
+ "xor",
26301
+ "implies",
26302
+ "if",
26303
+ "then",
26304
+ "else",
26305
+ "endif",
26306
+ "true",
26307
+ "false",
26308
+ "null",
26309
+ "invalid",
26310
+ "abs",
26311
+ "max",
26312
+ "min",
26313
+ "floor",
26314
+ "ceil",
26315
+ "mod",
26316
+ "div",
26317
+ "round",
26318
+ "sqrt",
26319
+ "exp",
26320
+ "ln",
26321
+ "log",
26322
+ "sum",
26323
+ "count",
26324
+ "exists",
26325
+ "forall",
26326
+ "oclIsUndefined",
26327
+ "oclIsKindOf",
26328
+ "oclIsTypeOf",
26329
+ "String",
26330
+ "Integer",
26331
+ "Real",
26332
+ "Boolean",
26333
+ "Set",
26334
+ "Bag",
26335
+ "Sequence",
26336
+ "Collection",
26337
+ // the subject-chain roots: every expression reads the dispatch
26338
+ // context through them — context, never air
26339
+ "sample",
26340
+ "family",
26341
+ "group",
26342
+ "model",
26343
+ "instrument",
26344
+ "specimen",
26345
+ "max_of",
26346
+ "min_of",
26347
+ "mean_of",
26348
+ "stddev_of",
26349
+ "count_of"
26350
+ ]);
26351
+ const globalExprNames = new Set(
26352
+ [
26353
+ ...(standard.symbols ?? []).map((s) => s.id),
26354
+ ...(standard.symbols ?? []).map((s) => s.id.split("/").pop() ?? ""),
26355
+ ...(standard.datums ?? []).map((d) => d.id),
26356
+ ...(standard.verdicts ?? []).map((v) => v.id),
26357
+ // the lookup tables: a dotted helper call's OBJECT is declared here —
26358
+ // the method name rides the declared object
26359
+ ...(standard.tables ?? []).map((v) => v.id),
26360
+ // the subject anatomy: a declared attribute is a declaration
26361
+ ...(standard.attributeDefinitions ?? []).map((a) => a.id),
26362
+ ...(standard.attributeDefinitions ?? []).map(
26363
+ (a) => a.id.split("/").pop() ?? ""
26364
+ ),
26365
+ // the calculations: a derivation may call a declared calculation
26366
+ // (twin-cert's lookupMPE) — the callable registry
26367
+ ...(standard.calculations ?? []).map((c) => c.id),
26368
+ ...(standard.calculations ?? []).map((c) => c.id.split("/").pop() ?? "")
26369
+ ].filter((x) => x !== "")
26370
+ );
26371
+ const symbolKinds = /* @__PURE__ */ new Map();
26372
+ for (const s of standard.symbols ?? []) {
26373
+ if (s.quantityKind) {
26374
+ symbolKinds.set(s.id, s.quantityKind);
26375
+ symbolKinds.set(s.id.split("/").pop() ?? "", s.quantityKind);
26376
+ }
26377
+ }
26378
+ const attributeKinds = /* @__PURE__ */ new Map();
26379
+ for (const a of standard.attributeDefinitions ?? []) {
26380
+ if (a.quantityKind) {
26381
+ attributeKinds.set(a.id, a.quantityKind);
26382
+ attributeKinds.set(
26383
+ a.id.split("/").pop() ?? "",
26384
+ a.quantityKind
26385
+ );
26386
+ }
26387
+ }
26388
+ const verdictKinds = /* @__PURE__ */ new Map();
26389
+ for (const v of standard.verdicts ?? []) {
26390
+ if (v.quantityKind) {
26391
+ verdictKinds.set(v.id, v.quantityKind);
26392
+ }
26393
+ }
26394
+ const tableColumnTypes = /* @__PURE__ */ new Map();
26395
+ for (const t of standard.tables ?? []) {
26396
+ const cols = /* @__PURE__ */ new Map();
26397
+ for (const c of t.columnDefs ?? []) {
26398
+ cols.set(c.name, (c.type || "").toLowerCase());
26399
+ }
26400
+ if (cols.size > 0) {
26401
+ tableColumnTypes.set(t.id, cols);
26402
+ }
26403
+ }
26404
+ const bare = (q) => q.split(":").pop() ?? q;
26405
+ const usesCovers = (uses, id) => uses.some((u) => {
26406
+ const tail = bare(u.replace(/\./g, ":"));
26407
+ return u === id || tail === id || u.endsWith("." + id);
26408
+ });
26409
+ const exprIds = (expr) => {
26410
+ const paths = expr.match(/[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*/g) ?? [];
26411
+ const out = [];
26412
+ const seen = /* @__PURE__ */ new Set();
26413
+ for (const p of paths) {
26414
+ if (p.includes(".")) {
26415
+ const segs = p.split(".");
26416
+ if (globalExprNames.has(segs[0])) {
26417
+ continue;
26418
+ }
26419
+ const finalSeg = segs[segs.length - 1];
26420
+ if (!seen.has(p)) {
26421
+ seen.add(p);
26422
+ if (!OCL_WORDS.has(finalSeg)) {
26423
+ out.push(finalSeg);
26424
+ }
26425
+ }
26426
+ continue;
26427
+ }
26428
+ if (!OCL_WORDS.has(p) && !seen.has(p)) {
26429
+ seen.add(p);
26430
+ out.push(p);
26431
+ }
26432
+ }
26433
+ return out;
26434
+ };
26435
+ const unresolvedIn = (expr, scope, uses) => {
26436
+ const scopeSet = /* @__PURE__ */ new Set([...scope, ...globalExprNames]);
26437
+ const seen = /* @__PURE__ */ new Set();
26438
+ const out = [];
26439
+ for (const id of exprIds(expr)) {
26440
+ if (seen.has(id)) {
26441
+ continue;
26442
+ }
26443
+ seen.add(id);
26444
+ if (OCL_WORDS.has(id) || scopeSet.has(id) || usesCovers(uses, id)) {
26445
+ continue;
26446
+ }
26447
+ out.push(id);
26448
+ }
26449
+ return out;
26450
+ };
26451
+ const mappedCalcIds = /* @__PURE__ */ new Set();
26452
+ {
26453
+ const mapsTo = standard.packageManifest?.mapsTo ?? [];
26454
+ for (const target of mapsTo) {
26455
+ if (!options.resolvePackage) {
26456
+ continue;
26457
+ }
26458
+ try {
26459
+ const depDir = options.resolvePackage(target);
26460
+ if (!depDir) {
26461
+ continue;
26462
+ }
26463
+ const dep = loadPackageWithIssues(depDir);
26464
+ for (const c of dep.standard?.calculations ?? []) {
26465
+ mappedCalcIds.add(c.id);
26466
+ mappedCalcIds.add(c.id.split("/").pop() ?? "");
26467
+ }
26468
+ } catch {
26469
+ }
26470
+ }
26471
+ for (const x of mappedCalcIds) {
26472
+ if (x !== "") {
26473
+ globalExprNames.add(x);
26474
+ }
26475
+ }
26476
+ }
26477
+ const INLINE_FUNCTION_WORDS = /* @__PURE__ */ new Set([
26478
+ "abs",
26479
+ "max",
26480
+ "min",
26481
+ "floor",
26482
+ "ceil",
26483
+ "round",
26484
+ "sqrt",
26485
+ "exp",
26486
+ "ln",
26487
+ "log",
26488
+ "mod",
26489
+ "sum",
26490
+ "count",
26491
+ "exists",
26492
+ "forall",
26493
+ // the series aggregations (register W4): the GUM type A vocabulary —
26494
+ // the statistics of a captured series; the evaluation is plurimath's
26495
+ "max_of",
26496
+ "min_of",
26497
+ "mean_of",
26498
+ "stddev_of",
26499
+ "count_of"
26500
+ ]);
26501
+ const DECLARATION_KINDS = /* @__PURE__ */ new Set([
26502
+ "symbol",
26503
+ "table",
26504
+ "datum",
26505
+ "verdict",
26506
+ "attribute",
26507
+ "process"
26508
+ ]);
26509
+ const CONTEXT_ROOTS = /* @__PURE__ */ new Set([
26510
+ "sample",
26511
+ "family",
26512
+ "group",
26513
+ "model",
26514
+ "instrument",
26515
+ "specimen"
26516
+ ]);
26517
+ const checkInlineLimit = (ownerKind, ownerId, limit, memberScope) => {
26518
+ let ast;
26519
+ try {
26520
+ ast = parseExpression(limit.expression);
26521
+ } catch (e) {
26522
+ err(
26523
+ "C171",
26524
+ `${ownerKind} ${ownerId}: the inline limit expression does not parse \u2014 ${String(e.message ?? e)} (expression-identifiers-resolve)`
26525
+ );
26526
+ return;
26527
+ }
26528
+ const ids = freeIdentifiers(ast);
26529
+ const args2 = limit.args ?? [];
26530
+ const argNames = new Set(args2.map((a) => a.name));
26531
+ if (memberScope === null && args2.length === 0 && ids.names.some((n) => !n.includes("."))) {
26532
+ err(
26533
+ "C171",
26534
+ `${ownerKind} ${ownerId}: the inline limit declares no arguments \u2014 every identifier must bind explicitly, args { name <- <declaration> } (expression-identifiers-resolve)`
26535
+ );
26536
+ }
26537
+ for (const call of new Set(ids.calls)) {
26538
+ if (INLINE_FUNCTION_WORDS.has(call)) {
26539
+ continue;
26540
+ }
26541
+ if (call.includes(".")) {
26542
+ const root = call.split(".")[0];
26543
+ if (argNames.has(root) || root === "self" || CONTEXT_ROOTS.has(root)) {
26544
+ continue;
26545
+ }
26546
+ }
26547
+ if (argNames.has(call)) {
26548
+ continue;
26549
+ }
26550
+ err(
26551
+ "C171",
26552
+ `${ownerKind} ${ownerId}: the limit calls "${call}(\u2026)", which no argument binds and which is not in the expression function vocabulary (abs max min floor ceil round sqrt exp ln log mod sum count exists forall) \u2014 air inside the formula (expression-identifiers-resolve)`
26553
+ );
26554
+ }
26555
+ for (const id of new Set(ids.names)) {
26556
+ const root = id.split(".")[0];
26557
+ if (id.includes(".") && (root === "self" || argNames.has(root) || CONTEXT_ROOTS.has(root))) {
26558
+ continue;
26559
+ }
26560
+ if (argNames.has(id)) {
26561
+ continue;
26562
+ }
26563
+ if (memberScope !== null && memberScope.has(id)) {
26564
+ continue;
26565
+ }
26566
+ const lawScoped = memberScope !== null;
26567
+ const fix = lawScoped ? "the law composes the containment only \u2014 its identifiers are the members" : "add args { " + id + " <- <declaration> } or remove it";
26568
+ err(
26569
+ lawScoped ? "C172" : "C171",
26570
+ `${ownerKind} ${ownerId}: the limit expression names "${id}", which no argument binds \u2014 ${fix} (${lawScoped ? "requirement-algebra-resolves" : "expression-identifiers-resolve"})`
26571
+ );
26572
+ }
26573
+ for (const a of args2) {
26574
+ if (a.source.includes(":")) {
26575
+ const segs = a.source.split(":");
26576
+ if (segs.some((s) => s.length === 0)) {
26577
+ err(
26578
+ "C171",
26579
+ `${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 a binding is <kind>:<id> in this package or <package>:<kind>:<id> across a uses edge (expression-identifiers-resolve)`
26580
+ );
26581
+ continue;
26582
+ }
26583
+ if (segs.length === 2) {
26584
+ const [kind, id] = segs;
26585
+ if (kind === "process") {
26586
+ const segs2 = id.split(".");
26587
+ const proc = (standard.processes ?? []).find(
26588
+ (pp) => pp.id === segs2[0]
26589
+ );
26590
+ if (!proc) {
26591
+ err(
26592
+ "C171",
26593
+ `${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}", which no declared process names \u2014 air inside the formula (expression-identifiers-resolve)`
26594
+ );
26595
+ } else if (segs2.length >= 2) {
26596
+ const stp = (proc.steps ?? []).find((ss) => ss.id === segs2[1]);
26597
+ if (!stp) {
26598
+ err(
26599
+ "C171",
26600
+ `${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 the process declares no step "${segs2[1]}" (expression-identifiers-resolve)`
26601
+ );
26602
+ } else if (segs2.length >= 3) {
26603
+ const io = segs2.slice(2).join(".");
26604
+ if (!(stp.sigInputs ?? []).includes(io) && !(stp.sigOutputs ?? []).includes(io)) {
26605
+ err(
26606
+ "C171",
26607
+ `${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 the step declares no io "${io}" (expression-identifiers-resolve)`
26608
+ );
26609
+ }
26610
+ }
26611
+ }
26612
+ continue;
26613
+ }
26614
+ if (kind !== "observable") {
26615
+ if (!DECLARATION_KINDS.has(kind)) {
26616
+ err(
26617
+ "C171",
26618
+ `${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}" \u2014 "${kind}" is not a declaration kind (symbol table datum verdict attribute observable) (expression-identifiers-resolve)`
26619
+ );
26620
+ continue;
26621
+ }
26622
+ const idRoot = id.split(".")[0];
26623
+ const idTail = id.split(".").pop() ?? id;
26624
+ if (!globalExprNames.has(id) && !globalExprNames.has(idRoot) && !globalExprNames.has(idTail)) {
26625
+ err(
26626
+ "C171",
26627
+ `${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}", which no declared ${kind} names \u2014 air inside the formula (expression-identifiers-resolve)`
26628
+ );
26629
+ }
26630
+ }
26631
+ continue;
26632
+ }
26633
+ continue;
26634
+ }
26635
+ if (a.source === "self" || a.source.startsWith("self.")) {
26636
+ continue;
26637
+ }
26638
+ const bare2 = (q) => q.split(":").pop() ?? q;
26639
+ const sourceBare = bare2(a.source.replace(/\./g, ":"));
26640
+ if (memberScope !== null) {
26641
+ if (!memberScope.has(a.source) && !memberScope.has(sourceBare)) {
26642
+ err(
26643
+ "C172",
26644
+ `requirement class ${ownerId}: the law binds "${a.name}" to "${a.source}", which is not a contained member (requirement-algebra-resolves)`
26645
+ );
26646
+ }
26647
+ continue;
26648
+ }
26649
+ if (!globalExprNames.has(a.source) && !globalExprNames.has(sourceBare) && !usesCovers(limit.uses, sourceBare)) {
26650
+ err(
26651
+ "C171",
26652
+ `${ownerKind} ${ownerId}: argument "${a.name}" binds to "${a.source}", which no symbol, datum, verdict, attribute, or uses entry declares \u2014 air inside the formula (expression-identifiers-resolve)`
26653
+ );
26654
+ }
26655
+ }
26656
+ const kindLabel = (k) => k === void 0 ? "an operand of unknown kind" : k === "TEXT" ? "text" : k === null ? "a bare number" : `the "${k}" quantity`;
26657
+ const argKindOf = (source) => {
26658
+ if (source.includes(":")) {
26659
+ const segs = source.split(":");
26660
+ if (segs.length !== 2) {
26661
+ return void 0;
26662
+ }
26663
+ const [kind, id] = segs;
26664
+ if (kind === "symbol") {
26665
+ return symbolKinds.get(id.split(".").pop() ?? id);
26666
+ }
26667
+ if (kind === "attribute") {
26668
+ return attributeKinds.get(id.split(".").pop() ?? id);
26669
+ }
26670
+ if (kind === "verdict") {
26671
+ return verdictKinds.get(id.split(".")[0]);
26672
+ }
26673
+ if (kind === "table") {
26674
+ const segs2 = id.split(".");
26675
+ const colType = segs2.length === 2 ? tableColumnTypes.get(segs2[0])?.get(segs2[1]) : void 0;
26676
+ return colType === "string" ? "TEXT" : void 0;
26677
+ }
26678
+ return void 0;
26679
+ }
26680
+ if (source === "self" || source.startsWith("self.")) {
26681
+ return void 0;
26682
+ }
26683
+ return symbolKinds.get(source) ?? attributeKinds.get(source) ?? void 0;
26684
+ };
26685
+ const kindConflicts = /* @__PURE__ */ new Set();
26686
+ const kindMixErr = (node, l, r) => {
26687
+ const key = renderExpression(node);
26688
+ if (kindConflicts.has(key)) {
26689
+ return;
26690
+ }
26691
+ kindConflicts.add(key);
26692
+ err(
26693
+ "C177",
26694
+ `${ownerKind} ${ownerId}: ${kindLabel(l)} is set against ${kindLabel(r)} in "${renderExpression(node)}" \u2014 the operands must share the quantity kind (kind-coherence)`
26695
+ );
26696
+ };
26697
+ const kindOf = (node) => {
26698
+ switch (node.type) {
26699
+ case "num":
26700
+ return null;
26701
+ case "str":
26702
+ return null;
26703
+ case "name": {
26704
+ const root = node.path[0];
26705
+ if (node.path.length > 1 && (root === "self" || CONTEXT_ROOTS.has(root))) {
26706
+ return void 0;
26707
+ }
26708
+ const arg = args2.find((a) => a.name === root);
26709
+ return arg ? argKindOf(arg.source) : void 0;
26710
+ }
26711
+ case "call": {
26712
+ if (node.callee.includes(".")) {
26713
+ return void 0;
26714
+ }
26715
+ const kinded = [
26716
+ "abs",
26717
+ "max",
26718
+ "min",
26719
+ "floor",
26720
+ "ceil",
26721
+ "round",
26722
+ "sqrt",
26723
+ "exp",
26724
+ "ln",
26725
+ "log",
26726
+ "mod"
26727
+ ];
26728
+ if (!kinded.includes(node.callee)) {
26729
+ return null;
26730
+ }
26731
+ let acc = void 0;
26732
+ for (const a of node.args) {
26733
+ const k = kindOf(a);
26734
+ if (k === void 0) {
26735
+ continue;
26736
+ }
26737
+ if (acc === void 0 || acc === null) {
26738
+ acc = k;
26739
+ continue;
26740
+ }
26741
+ if (k !== void 0 && k !== null && k !== acc) {
26742
+ kindMixErr(node, acc, k);
26743
+ }
26744
+ }
26745
+ return acc;
26746
+ }
26747
+ case "unop":
26748
+ return node.op === "not" ? null : kindOf(node.operand);
26749
+ case "nav":
26750
+ return node.op === "select" ? void 0 : null;
26751
+ case "binop": {
26752
+ if (["<=", ">=", "<", ">", "=", "!=", "\u2260"].includes(node.op)) {
26753
+ const l2 = kindOf(node.left);
26754
+ const r2 = kindOf(node.right);
26755
+ if (l2 !== void 0 && r2 !== void 0 && l2 !== null && r2 !== null && l2 !== r2) {
26756
+ kindMixErr(node, l2, r2);
26757
+ }
26758
+ return null;
26759
+ }
26760
+ if (["and", "or", "xor", "implies"].includes(node.op)) {
26761
+ kindOf(node.left);
26762
+ kindOf(node.right);
26763
+ return null;
26764
+ }
26765
+ const l = kindOf(node.left);
26766
+ const r = kindOf(node.right);
26767
+ if (l !== void 0 && r !== void 0 && l !== null && r !== null && l !== r) {
26768
+ kindMixErr(node, l, r);
26769
+ }
26770
+ return l !== void 0 && l !== null ? l : r;
26771
+ }
26772
+ }
26773
+ };
26774
+ kindOf(ast);
26775
+ };
26776
+ for (const r of standard.requirements ?? []) {
26777
+ if (r.limit?.argsBound) {
26778
+ checkInlineLimit("requirement", r.id, r.limit, null);
26779
+ continue;
26780
+ }
26781
+ const expr = r.limit?.expression;
26782
+ if (!expr) {
26783
+ continue;
26784
+ }
26785
+ const ocl = expr.replace(/^ocl\{/, "").replace(/\}$/, "");
26786
+ const uses = r.limit?.uses ?? [];
26787
+ for (const id of unresolvedIn(ocl, [], uses)) {
26788
+ err(
26789
+ "C171",
26790
+ `requirement ${r.id}: the limit expression names "${id}", which no uses entry, symbol, datum, or verdict declares \u2014 air inside the formula (expression-identifiers-resolve)`
26791
+ );
26792
+ }
26793
+ }
26794
+ const resolveInlineCarrier = (ownerKind, ownerId, what, src, scope) => {
26795
+ let ast;
26796
+ try {
26797
+ ast = parseExpression(src);
26798
+ } catch (e) {
26799
+ err(
26800
+ "C171",
26801
+ `${ownerKind} ${ownerId}: the ${what} does not parse \u2014 ${String(e.message ?? e)} (expression-identifiers-resolve)`
26802
+ );
26803
+ return;
26804
+ }
26805
+ const ids = freeIdentifiers(ast);
26806
+ for (const call of new Set(ids.calls)) {
26807
+ if (INLINE_FUNCTION_WORDS.has(call)) {
26808
+ continue;
26809
+ }
26810
+ if (call.includes(".")) {
26811
+ const root = call.split(".")[0];
26812
+ if (scope.has(root) || globalExprNames.has(root) || root === "self" || CONTEXT_ROOTS.has(root)) {
26813
+ continue;
26814
+ }
26815
+ }
26816
+ if (scope.has(call) || globalExprNames.has(call)) {
26817
+ continue;
26818
+ }
26819
+ err(
26820
+ "C171",
26821
+ `${ownerKind} ${ownerId}: the ${what} calls "${call}(\u2026)", which nothing declares and which is not in the expression function vocabulary \u2014 air inside the formula (expression-identifiers-resolve)`
26822
+ );
26823
+ }
26824
+ for (const id of new Set(ids.names)) {
26825
+ const root = id.split(".")[0];
26826
+ if (id.includes(".") && (scope.has(root) || root === "self" || CONTEXT_ROOTS.has(root))) {
26827
+ continue;
26828
+ }
26829
+ if (scope.has(id)) {
26830
+ continue;
26831
+ }
26832
+ if (globalExprNames.has(id) || globalExprNames.has(id.split(".").pop() ?? id)) {
26833
+ continue;
26834
+ }
26835
+ err(
26836
+ "C171",
26837
+ `${ownerKind} ${ownerId}: the ${what} names "${id}", which nothing in scope declares \u2014 air inside the formula (expression-identifiers-resolve)`
26838
+ );
26839
+ }
26840
+ };
26841
+ for (const v of standard.verdicts ?? []) {
26842
+ const expr = v.derive;
26843
+ if (!expr) {
26844
+ continue;
26845
+ }
26846
+ const inputs = v.inputs ?? [];
26847
+ if (v.deriveBound) {
26848
+ resolveInlineCarrier("verdict", v.id, "derive", expr, new Set(inputs));
26849
+ continue;
26850
+ }
26851
+ const ocl = expr.replace(/^ocl\{/, "").replace(/\}$/, "");
26852
+ for (const id of unresolvedIn(ocl, inputs, [])) {
26853
+ err(
26854
+ "C171",
26855
+ `verdict ${v.id}: the derive expression names "${id}", which no input declares \u2014 air inside the formula (expression-identifiers-resolve)`
26856
+ );
26857
+ }
26858
+ }
26859
+ for (const t of standard.conformanceTests ?? []) {
26860
+ const scope = (t.variables ?? []).map((v) => v.name);
26861
+ for (const v of t.variables ?? []) {
26862
+ if (!v.derivation) {
26863
+ continue;
26864
+ }
26865
+ if (v.derivationBound) {
26866
+ resolveInlineCarrier(
26867
+ "conformance test",
26868
+ t.id,
26869
+ `variable ${v.name}'s derivation`,
26870
+ v.derivation,
26871
+ new Set(scope)
26872
+ );
26873
+ continue;
26874
+ }
26875
+ const ocl = v.derivation.replace(/^ocl\{/, "").replace(/\}$/, "");
26876
+ for (const id of unresolvedIn(ocl, scope, [])) {
26877
+ err(
26878
+ "C171",
26879
+ `conformance test ${t.id}: variable ${v.name}'s derivation names "${id}", which no sibling variable, symbol, datum, or verdict declares \u2014 air inside the formula (expression-identifiers-resolve)`
26880
+ );
26881
+ }
26882
+ }
26883
+ }
26884
+ for (const c of standard.constraints ?? []) {
26885
+ if (!c.checkBound || !c.check) {
26886
+ continue;
26887
+ }
26888
+ const cArgs = c.args ?? [];
26889
+ const cScope = new Set(cArgs.map((a) => a.name));
26890
+ for (const a of cArgs) {
26891
+ if (a.source.includes(":")) {
26892
+ const segs = a.source.split(":");
26893
+ if (segs.length === 2 && segs[0] !== "observable") {
26894
+ const [kind, id] = segs;
26895
+ if (!DECLARATION_KINDS.has(kind)) {
26896
+ err(
26897
+ "C171",
26898
+ `constraint ${c.id}: argument "${a.name}" binds to "${a.source}" \u2014 "${kind}" is not a declaration kind (expression-identifiers-resolve)`
26899
+ );
26900
+ } else {
26901
+ const idRoot = id.split(".")[0];
26902
+ const idTail = id.split(".").pop() ?? id;
26903
+ if (!globalExprNames.has(id) && !globalExprNames.has(idRoot) && !globalExprNames.has(idTail)) {
26904
+ err(
26905
+ "C171",
26906
+ `constraint ${c.id}: argument "${a.name}" binds to "${a.source}", which no declared ${kind} names \u2014 air inside the formula (expression-identifiers-resolve)`
26907
+ );
26908
+ }
26909
+ }
26910
+ }
26911
+ continue;
26912
+ }
26913
+ if (a.source === "self" || a.source.startsWith("self.")) {
26914
+ continue;
26915
+ }
26916
+ const bare2 = a.source.split(":").pop() ?? a.source;
26917
+ if (!globalExprNames.has(a.source) && !globalExprNames.has(bare2)) {
26918
+ err(
26919
+ "C171",
26920
+ `constraint ${c.id}: argument "${a.name}" binds to "${a.source}", which nothing declares \u2014 air inside the formula (expression-identifiers-resolve)`
26921
+ );
26922
+ }
26923
+ }
26924
+ resolveInlineCarrier("constraint", c.id, "check", c.check, cScope);
26925
+ try {
26926
+ const ast = parseExpression(c.check);
26927
+ const booleanTop = ast.type === "binop" && [
26928
+ "<=",
26929
+ ">=",
26930
+ "<",
26931
+ ">",
26932
+ "=",
26933
+ "!=",
26934
+ "\u2260",
26935
+ "and",
26936
+ "or",
26937
+ "xor",
26938
+ "implies"
26939
+ ].includes(ast.op) || ast.type === "nav" && ["forAll", "exists"].includes(ast.op);
26940
+ if (!booleanTop) {
26941
+ err(
26942
+ "C84",
26943
+ `constraint ${c.id}: the check does not evaluate to a boolean \u2014 an invariant is one comparison or logical composition (constraint-shape)`
26944
+ );
26945
+ }
26946
+ } catch {
26947
+ }
26948
+ }
26949
+ const memberSet = /* @__PURE__ */ new Map();
26950
+ for (const rc of standard.requirementClasses ?? []) {
26951
+ memberSet.set(rc.id, new Set((rc.members ?? []).map(String)));
26952
+ }
26953
+ for (const rc of standard.requirementClasses ?? []) {
26954
+ const law = rc.limit?.expression;
26955
+ const members = memberSet.get(rc.id) ?? /* @__PURE__ */ new Set();
26956
+ if (!law) {
26957
+ continue;
26958
+ }
26959
+ if (rc.limit?.argsBound) {
26960
+ checkInlineLimit("requirement class", rc.id, rc.limit, members);
26961
+ const covered2 = /* @__PURE__ */ new Set();
26962
+ try {
26963
+ for (const n of freeIdentifiers(parseExpression(law)).names) {
26964
+ covered2.add(n);
26965
+ }
26966
+ } catch {
26967
+ }
26968
+ for (const a of rc.limit.args ?? []) {
26969
+ covered2.add(a.name);
26970
+ covered2.add(a.source);
26971
+ }
26972
+ for (const m of members) {
26973
+ if (!covered2.has(m)) {
26974
+ warn(
26975
+ "C172",
26976
+ `requirement class ${rc.id}: member ${m} does not appear in the law \u2014 either it is always-required (add it with \`and\`) or it is orphaned (requirement-algebra-resolves)`
26977
+ );
26978
+ }
26979
+ }
26980
+ continue;
26981
+ }
26982
+ const ocl = law.replace(/^ocl\{/, "").replace(/\}$/, "");
26983
+ const ids = (ocl.match(/[A-Za-z_][A-Za-z0-9_]*/g) ?? []).filter(
26984
+ (x) => !OCL_WORDS.has(x)
26985
+ );
26986
+ const lawIds = /* @__PURE__ */ new Set();
26987
+ for (const id of ids) {
26988
+ lawIds.add(id);
26989
+ if (!members.has(id)) {
26990
+ err(
26991
+ "C172",
26992
+ `requirement class ${rc.id}: the law names "${id}", which is not a contained member \u2014 the algebra composes the containment only (requirement-algebra-resolves)`
26993
+ );
26994
+ }
26995
+ }
26996
+ for (const m of members) {
26997
+ if (!lawIds.has(m)) {
26998
+ warn(
26999
+ "C172",
27000
+ `requirement class ${rc.id}: member ${m} does not appear in the law \u2014 either it is always-required (add it with \`and\`) or it is orphaned (requirement-algebra-resolves)`
27001
+ );
27002
+ }
27003
+ }
27004
+ }
27005
+ const DEPRECATION_GENERATION = "v3.4";
27006
+ const generationRank = (g) => {
27007
+ const m = g.match(/^v(\d+)(?:\.(\d+))?$/);
27008
+ if (!m) {
27009
+ return -1;
27010
+ }
27011
+ return Number(m[1]) * 1e3 + Number(m[2] ?? "0");
27012
+ };
27013
+ try {
27014
+ const mf = readPackageManifest(dir);
27015
+ if (mf.language !== void 0) {
27016
+ if (!/^v\d+(\.\d+)?$/.test(mf.language)) {
27017
+ err(
27018
+ "C176",
27019
+ `the declared language "${mf.language}" is not a generation (v<major>[.<minor>]) (language-declared-wellformed)`
27020
+ );
27021
+ } else if (generationRank(mf.language) >= generationRank(DEPRECATION_GENERATION)) {
27022
+ let legacy = 0;
27023
+ for (const r of standard.requirements ?? []) {
27024
+ if (r.limit && !r.limit.argsBound && r.limit.expression) {
27025
+ legacy += 1;
27026
+ }
27027
+ }
27028
+ for (const v of standard.verdicts ?? []) {
27029
+ if (v.derive && !v.deriveBound) {
27030
+ legacy += 1;
27031
+ }
27032
+ }
27033
+ for (const t of standard.conformanceTests ?? []) {
27034
+ for (const v of t.variables ?? []) {
27035
+ if (v.derivation && !v.derivationBound) {
27036
+ legacy += 1;
27037
+ }
27038
+ }
27039
+ for (const p of t.preconditions ?? []) {
27040
+ if (p.check && !p.checkBound) {
27041
+ legacy += 1;
27042
+ }
27043
+ }
27044
+ }
27045
+ for (const c of standard.constraints ?? []) {
27046
+ if (c.check && !c.checkBound) {
27047
+ legacy += 1;
27048
+ }
27049
+ }
27050
+ if (legacy > 0) {
27051
+ warn(
27052
+ "C178",
27053
+ `${legacy} quoted expression carrier${legacy === 1 ? "" : "s"} \u2014 the ocl{\u2026} string form is deprecated as of ${DEPRECATION_GENERATION}; migrate to the inline blocks (expression { \u2026 }, derive { \u2026 }, derivation { \u2026 }, check { \u2026 }) (legacy-carrier-deprecated)`
27054
+ );
27055
+ }
27056
+ }
27057
+ }
27058
+ } catch {
27059
+ }
27060
+ {
27061
+ const seriesVariables = /* @__PURE__ */ new Map();
27062
+ for (const t of standard.conformanceTests ?? []) {
27063
+ for (const v of t.variables ?? []) {
27064
+ seriesVariables.set(v.name, v.series !== null);
27065
+ }
27066
+ }
27067
+ for (const b of standard.uncertaintyBudgets ?? []) {
27068
+ if (!b.target) {
27069
+ err(
27070
+ "C179",
27071
+ `uncertainty_budget ${b.id}: declares no target \u2014 the budget backs a declared verdict's measured quantity (uncertainty-budget-resolves)`
27072
+ );
27073
+ } else if (!(standard.verdicts ?? []).some((v) => v.id === b.target)) {
27074
+ err(
27075
+ "C179",
27076
+ `uncertainty_budget ${b.id}: target "${b.target}" is not a declared verdict \u2014 the budget backs a measured quantity the verdicts own (uncertainty-budget-resolves)`
27077
+ );
27078
+ }
27079
+ if (b.components.length === 0) {
27080
+ warn(
27081
+ "C179",
27082
+ `uncertainty_budget ${b.id}: declares no components \u2014 an empty budget states no uncertainty (uncertainty-budget-resolves)`
27083
+ );
27084
+ }
27085
+ if (b.coverageK && !(Number(b.coverageK) > 0)) {
27086
+ err(
27087
+ "C179",
27088
+ `uncertainty_budget ${b.id}: coverage k "${b.coverageK}" is not a positive number (uncertainty-budget-resolves)`
27089
+ );
27090
+ }
27091
+ for (const c of b.components) {
27092
+ if (c.type === "A") {
27093
+ if (!c.series) {
27094
+ err(
27095
+ "C179",
27096
+ `uncertainty_budget ${b.id}: component ${c.id} is Type A but names no series \u2014 the statistics compute from a declared captured series (uncertainty-budget-resolves)`
27097
+ );
27098
+ } else if (!seriesVariables.has(c.series)) {
27099
+ err(
27100
+ "C179",
27101
+ `uncertainty_budget ${b.id}: component ${c.id}'s series "${c.series}" is not a declared test variable (uncertainty-budget-resolves)`
27102
+ );
27103
+ } else if (!seriesVariables.get(c.series)) {
27104
+ err(
27105
+ "C179",
27106
+ `uncertainty_budget ${b.id}: component ${c.id}'s series "${c.series}" declares no series shape \u2014 a Type A evaluation needs the captured series' axes and cell (uncertainty-budget-resolves)`
27107
+ );
27108
+ }
27109
+ } else {
27110
+ if (!c.distribution) {
27111
+ err(
27112
+ "C179",
27113
+ `uncertainty_budget ${b.id}: component ${c.id} is Type B but states no distribution (uncertainty-budget-resolves)`
27114
+ );
27115
+ }
27116
+ if (!c.halfWidth) {
27117
+ err(
27118
+ "C179",
27119
+ `uncertainty_budget ${b.id}: component ${c.id} is Type B but states no half_width \u2014 the distribution spans a half-width (uncertainty-budget-resolves)`
27120
+ );
27121
+ }
27122
+ }
27123
+ }
27124
+ }
27125
+ }
27126
+ for (const p of standard.processes ?? []) {
27127
+ for (const st of p.steps ?? []) {
27128
+ if (!st.completion) {
27129
+ continue;
27130
+ }
27131
+ const ios = /* @__PURE__ */ new Set([...st.sigInputs, ...st.sigOutputs]);
27132
+ let ids;
27133
+ try {
27134
+ ids = freeIdentifiers(
27135
+ parseExpression(
27136
+ st.completion.replace(/^ocl\{/, "").replace(/\}$/, "")
27137
+ )
27138
+ );
27139
+ } catch (e) {
27140
+ err(
27141
+ "C173",
27142
+ `process ${p.id}: step "${st.id}" completion does not parse \u2014 ${String(e.message ?? e)} \u2014 the completion is one expression over the step's ios (step-plane-refs-resolve)`
27143
+ );
27144
+ continue;
27145
+ }
27146
+ for (const call of new Set(ids.calls)) {
27147
+ if (!INLINE_FUNCTION_WORDS.has(call)) {
27148
+ err(
27149
+ "C173",
27150
+ `process ${p.id}: step "${st.id}" completion calls "${call}(\u2026)", which is not in the expression function vocabulary (step-plane-refs-resolve)`
27151
+ );
27152
+ }
27153
+ }
27154
+ for (const id of new Set(ids.names)) {
27155
+ const root = id.split(".")[0];
27156
+ if (id.includes(".") && (root === "self" || CONTEXT_ROOTS.has(root))) {
27157
+ continue;
27158
+ }
27159
+ if (ios.has(id) || ios.has(root)) {
27160
+ continue;
27161
+ }
27162
+ err(
27163
+ "C173",
27164
+ `process ${p.id}: step "${st.id}" completion names "${id}", which is not a declared io of the step \u2014 the completion reads the step's own inputs and outputs (step-plane-refs-resolve)`
27165
+ );
27166
+ }
27167
+ }
27168
+ }
27169
+ try {
27170
+ const mf = readPackageManifest(dir);
27171
+ const eds = (mf.editions ?? []).map(String);
27172
+ if (eds.length > 1) {
27173
+ const map = JSON.parse(
27174
+ readFileSync5(join4(dir, "edition-mapping.json"), "utf8")
27175
+ );
27176
+ if (map.kind !== "primmel-edition-mapping/1") {
27177
+ err(
27178
+ "C170",
27179
+ `edition-mapping.json: kind "${String(map.kind)}" is not primmel-edition-mapping/1 (edition-lineage-declared)`
27180
+ );
27181
+ } else {
27182
+ const fromEd = map.from?.edition === void 0 ? void 0 : String(map.from.edition);
27183
+ const toEd = map.to?.edition === void 0 ? void 0 : String(map.to.edition);
27184
+ for (const [side, ed] of [
27185
+ ["from", fromEd],
27186
+ ["to", toEd]
27187
+ ]) {
27188
+ if (!ed || !eds.includes(ed)) {
27189
+ err(
27190
+ "C170",
27191
+ `edition-mapping.json: the ${side} edition ${String(ed)} is not among the manifest's declared editions [${eds.join(", ")}] (edition-lineage-declared)`
27192
+ );
27193
+ }
27194
+ }
27195
+ }
27196
+ }
27197
+ } catch (e) {
27198
+ const code = e.code;
27199
+ if (code === "ENOENT") {
27200
+ const eds = (() => {
27201
+ try {
27202
+ return (readPackageManifest(dir).editions ?? []).map(
27203
+ String
27204
+ );
27205
+ } catch {
27206
+ return [];
27207
+ }
27208
+ })();
27209
+ if (eds.length > 1) {
27210
+ err(
27211
+ "C170",
27212
+ `the package declares ${eds.length} editions [${eds.join(", ")}] but ships no edition-mapping.json \u2014 the cross-edition linkage is an artifact, never implicit (edition-lineage-declared)`
27213
+ );
27214
+ }
27215
+ } else if (e instanceof SyntaxError) {
27216
+ err(
27217
+ "C170",
27218
+ `edition-mapping.json is not valid JSON: ${e.message} (edition-lineage-declared)`
27219
+ );
27220
+ }
27221
+ }
27222
+ const methodTargetIds = (s) => /* @__PURE__ */ new Set([
27223
+ ...(s.processes ?? []).map((p) => p.id),
27224
+ ...(s.conformanceTests ?? []).map((x) => x.id)
27225
+ ]);
27226
+ const localMethodIds = methodTargetIds(standard);
27227
+ const scopedMethodIds = /* @__PURE__ */ new Map();
27228
+ const resolveCitation = (elemId, ref) => {
27229
+ const colon = ref.indexOf(":");
27230
+ if (colon <= 0) {
27231
+ if (!localMethodIds.has(ref)) {
27232
+ err(
27233
+ "C168",
27234
+ `${elemId}: the reference "${ref}" names no process or conformance test declared in this package (method-ref-resolves)`
27235
+ );
27236
+ }
27237
+ return;
27238
+ }
27239
+ if (!options.resolvePackage) {
27240
+ return;
27241
+ }
27242
+ const pkgId = ref.slice(0, colon);
27243
+ const localId = ref.slice(colon + 1);
27244
+ let ids = scopedMethodIds.get(pkgId);
27245
+ if (!ids) {
27246
+ ids = /* @__PURE__ */ new Set();
27247
+ try {
27248
+ const depDir = options.resolvePackage(pkgId);
27249
+ if (depDir) {
27250
+ const dep = loadPackageWithIssues(depDir);
27251
+ ids = methodTargetIds(dep.standard);
27252
+ }
27253
+ } catch {
27254
+ }
27255
+ scopedMethodIds.set(pkgId, ids);
27256
+ }
27257
+ if (!ids.has(localId)) {
27258
+ err(
27259
+ "C168",
27260
+ `${elemId}: the reference "${ref}" names no process or conformance test declared in package "${pkgId}" (method-ref-resolves)`
27261
+ );
27262
+ }
27263
+ };
27264
+ for (const t of standard.conformanceTests ?? []) {
27265
+ const ref = t.methodRef;
27266
+ if (ref) {
27267
+ resolveCitation(t.id, ref);
27268
+ }
27269
+ }
27270
+ for (const pr of standard.processes ?? []) {
27271
+ const raw = pr;
27272
+ for (const st of raw.steps ?? []) {
27273
+ const call = st.calls || st.signatureBlock?.match(/\bcalls +([\w:/.-]+)/)?.[1];
27274
+ if (call) {
27275
+ resolveCitation(`${pr.id}/step/${st.id ?? ""}`, call);
27276
+ }
27277
+ }
27278
+ }
24766
27279
  const ASPECT_FAMILY = {
24767
27280
  metadata: "is",
24768
27281
  provenance: "is",
@@ -25650,7 +28163,7 @@ function checkPackage(dir, options = {}) {
25650
28163
  `constraint ${c.id}: stereotype "${c.stereotype || "(none)"}" \u2014 a constraint is always \xABinv\xBB, the subject's declaration-level invariant (constraint-shape)`
25651
28164
  );
25652
28165
  }
25653
- if (!OCL_CHECK.test(c.check)) {
28166
+ if (!c.checkBound && !OCL_CHECK.test(c.check)) {
25654
28167
  err(
25655
28168
  "C84",
25656
28169
  `constraint ${c.id}: check is not one OCL boolean expression ocl{\u2026} over the subject's declared anatomy (constraint-shape)`
@@ -28745,9 +31258,9 @@ function checkPackage(dir, options = {}) {
28745
31258
  if (!dataclassByEntity.has(c.id)) {
28746
31259
  dataclassByEntity.set(c.id, c);
28747
31260
  }
28748
- const bare = c.id.includes("#") ? c.id.slice(0, c.id.indexOf("#")) : c.id;
28749
- if (!dataclassByEntity.has(bare)) {
28750
- dataclassByEntity.set(bare, c);
31261
+ const bare2 = c.id.includes("#") ? c.id.slice(0, c.id.indexOf("#")) : c.id;
31262
+ if (!dataclassByEntity.has(bare2)) {
31263
+ dataclassByEntity.set(bare2, c);
28751
31264
  }
28752
31265
  }
28753
31266
  const whereFields = (where) => {
@@ -30345,6 +32858,101 @@ function checkVerdictChains(standard) {
30345
32858
  }
30346
32859
  return issues;
30347
32860
  }
32861
+ function checkLmlAligned(standard) {
32862
+ const issues = [];
32863
+ const err = (check, message) => issues.push({ check, severity: "error", message });
32864
+ const warn = (check, message) => issues.push({ check, severity: "warning", message });
32865
+ const namespaceIds = new Set((standard.namespaces ?? []).map((n) => n.id));
32866
+ const dataclassIds = /* @__PURE__ */ new Set();
32867
+ for (const c of standard.dataclasses ?? []) {
32868
+ dataclassIds.add(c.id);
32869
+ dataclassIds.add(c.id.replace(/#data$/, ""));
32870
+ }
32871
+ const symbolIds = new Set((standard.symbols ?? []).map((s) => s.id));
32872
+ const datumIds = new Set((standard.datums ?? []).map((d) => d.id));
32873
+ const CLAUSE_CITATION = /clause-\d|§\d/i;
32874
+ for (const d of standard.datums ?? []) {
32875
+ if (!d.description) {
32876
+ continue;
32877
+ }
32878
+ if (CLAUSE_CITATION.test(d.description)) {
32879
+ err(
32880
+ "C158",
32881
+ `datum ${d.id}: the description cites a clause \u2014 a reference in prose belongs in a urn reference, not the quarantined free text (prose-quarantine)`
32882
+ );
32883
+ } else if (d.description.includes("TODO.roadmap")) {
32884
+ warn(
32885
+ "C158",
32886
+ `datum ${d.id}: the description carries the unfinished-prose marker TODO.roadmap (prose-quarantine)`
32887
+ );
32888
+ }
32889
+ }
32890
+ for (const w of standard.wireMappings ?? []) {
32891
+ if (w.namespaceRef && !namespaceIds.has(w.namespaceRef)) {
32892
+ err(
32893
+ "C159",
32894
+ `mapping ${w.id}: namespace "${w.namespaceRef}" names no declared namespace block (urn-only-refs)`
32895
+ );
32896
+ }
32897
+ }
32898
+ for (const c of standard.checks ?? []) {
32899
+ for (const inp of c.inputs ?? []) {
32900
+ if (!(datumIds.has(inp) || symbolIds.has(inp))) {
32901
+ err(
32902
+ "C160",
32903
+ `check ${c.id}: input "${inp}" resolves to no declared datum or symbol \u2014 the check consumes an undeclared name (signature-closure)`
32904
+ );
32905
+ }
32906
+ }
32907
+ }
32908
+ for (const d of standard.datums ?? []) {
32909
+ for (const r of d.renders ?? []) {
32910
+ if (!MATH_NOTATIONS.includes(r.notation)) {
32911
+ err(
32912
+ "C161",
32913
+ `datum ${d.id}: render notation "${r.notation}" is outside the closed vocabulary (${MATH_NOTATIONS.join("|")}) (check-surface)`
32914
+ );
32915
+ }
32916
+ }
32917
+ }
32918
+ const metaNamespace = standard.meta?.namespace ?? "";
32919
+ if (metaNamespace && namespaceIds.size > 0 && !namespaceIds.has(metaNamespace)) {
32920
+ err(
32921
+ "C162",
32922
+ `metadata namespace "${metaNamespace}" names no declared namespace block (namespace-coherence)`
32923
+ );
32924
+ }
32925
+ for (const w of standard.wireMappings ?? []) {
32926
+ if (!MAPPING_FORMATS.includes(w.format)) {
32927
+ err(
32928
+ "C164",
32929
+ `mapping ${w.id}: format "${w.format}" is outside the wire vocabulary (${MAPPING_FORMATS.join("|")}) (wire-mapping-coverage)`
32930
+ );
32931
+ }
32932
+ if (dataclassIds.size > 0 && !dataclassIds.has(w.target)) {
32933
+ err(
32934
+ "C164",
32935
+ `mapping ${w.id}: the class "${w.target}" is no declared dataclass \u2014 a class serialized to a format carries the declared mapping (wire-mapping-coverage)`
32936
+ );
32937
+ }
32938
+ }
32939
+ const QUALIFIED_REF = /^[a-z]+:[A-Za-z0-9_-]+$/;
32940
+ for (const d of standard.datums ?? []) {
32941
+ if (d.unit && !QUALIFIED_REF.test(d.unit)) {
32942
+ err(
32943
+ "C167",
32944
+ `datum ${d.id}: unit "${d.unit}" is bare \u2014 a unit reference uses the qualified <namespace>:<id> form (si:\u2026, unitsdb:\u2026) (qualified-unit-reference)`
32945
+ );
32946
+ }
32947
+ if (d.quantityKind && !QUALIFIED_REF.test(d.quantityKind)) {
32948
+ err(
32949
+ "C167",
32950
+ `datum ${d.id}: quantity_kind "${d.quantityKind}" is bare \u2014 a quantity-kind reference uses the qualified <namespace>:<id> form (si:\u2026, unitsdb:\u2026) (qualified-unit-reference)`
32951
+ );
32952
+ }
32953
+ }
32954
+ return issues;
32955
+ }
30348
32956
  function checkEditionLifecycle(dir, standard) {
30349
32957
  const issues = [];
30350
32958
  const err = (check, message) => issues.push({ check, severity: "error", message });
@@ -30546,6 +33154,143 @@ function findCycle(adj) {
30546
33154
  return cycle;
30547
33155
  }
30548
33156
 
33157
+ // src/fmt.ts
33158
+ import { readFileSync as readFileSync6, readdirSync as readdirSync4, statSync as statSync3, writeFileSync } from "node:fs";
33159
+ import { join as join5 } from "node:path";
33160
+
33161
+ // src/ser-des/dump.ts
33162
+ function dump(model, dumpers) {
33163
+ let out = "";
33164
+ if (model.root !== null) {
33165
+ out += "root " + model.root.id + "\n\n";
33166
+ }
33167
+ out += dumpMetadata(model.meta) + "\n";
33168
+ const childIds = /* @__PURE__ */ new Set();
33169
+ for (const p of model.processes) {
33170
+ for (const c of p.children) {
33171
+ childIds.add(c);
33172
+ }
33173
+ }
33174
+ const processMap = new Map(model.processes.map((p) => [p.id, p]));
33175
+ const memberIds = /* @__PURE__ */ new Set();
33176
+ for (const rc of model.requirementClasses ?? []) {
33177
+ for (const m of rc.members ?? []) {
33178
+ memberIds.add(m);
33179
+ }
33180
+ }
33181
+ const requirementMap = new Map(
33182
+ (model.requirements ?? []).map((r) => [r.id, r])
33183
+ );
33184
+ const classMap = new Map(
33185
+ (model.requirementClasses ?? []).map((rc) => [rc.id, rc])
33186
+ );
33187
+ const dumpersRef = dumpers;
33188
+ const dumpClassTree = (rcId) => {
33189
+ const rc = classMap.get(rcId);
33190
+ if (!rc) {
33191
+ return "";
33192
+ }
33193
+ const base = dumpersRef.requirementClasses(rc);
33194
+ if (!rc.members || rc.members.length === 0) {
33195
+ return base;
33196
+ }
33197
+ const inner = rc.members.map((m) => {
33198
+ const body = dumpersRef.requirements(requirementMap.get(m));
33199
+ return body.split("\n").filter((l) => l !== "").map((l) => " " + l).join("\n");
33200
+ }).join("\n");
33201
+ return base.slice(0, base.lastIndexOf("}")) + inner + "\n}\n";
33202
+ };
33203
+ Object.keys(dumpers).forEach((field) => {
33204
+ if (field === "processes") {
33205
+ for (const p of model.processes) {
33206
+ if (!childIds.has(p.id)) {
33207
+ out += dumpProcessTree(p, processMap);
33208
+ }
33209
+ }
33210
+ return;
33211
+ }
33212
+ if (field === "requirements") {
33213
+ for (const r of model.requirements ?? []) {
33214
+ if (!memberIds.has(r.id)) {
33215
+ out += dumpersRef.requirements(r);
33216
+ }
33217
+ }
33218
+ return;
33219
+ }
33220
+ if (field === "requirementClasses") {
33221
+ for (const rc of model.requirementClasses ?? []) {
33222
+ out += dumpClassTree(rc.id);
33223
+ }
33224
+ return;
33225
+ }
33226
+ const items = model[field];
33227
+ const dumper = dumpers[field];
33228
+ for (const item of items) {
33229
+ out += dumper(item);
33230
+ }
33231
+ });
33232
+ return out;
33233
+ }
33234
+
33235
+ // src/ser-des/index.ts
33236
+ function load(mmelString, options = {}) {
33237
+ const context = parse(mmelString, PARSER_CONFIG, options);
33238
+ return resolve(context, RESOLVER_CONFIG);
33239
+ }
33240
+ function loadFile(filePath, options = {}) {
33241
+ const content = preprocessIncludes(filePath);
33242
+ return load(content, options);
33243
+ }
33244
+ function dump2(standard) {
33245
+ return dump(standard, DUMPER_CONFIG);
33246
+ }
33247
+
33248
+ // src/fmt.ts
33249
+ var ALLOWLIST = ".primmel-allowlist.prl";
33250
+ function walkPrl(dir, out = []) {
33251
+ for (const e of readdirSync4(dir).sort()) {
33252
+ const p = join5(dir, e);
33253
+ if (statSync3(p).isDirectory()) {
33254
+ walkPrl(p, out);
33255
+ } else if (e.endsWith(".prl") && e !== ALLOWLIST) {
33256
+ out.push(p);
33257
+ }
33258
+ }
33259
+ return out;
33260
+ }
33261
+ function fmtPackage(dir, check = false) {
33262
+ const result = { dir, files: [], written: 0 };
33263
+ for (const file of walkPrl(dir)) {
33264
+ const src = readFileSync6(file, "utf8");
33265
+ if (/^\s*include\s+"/m.test(src)) {
33266
+ result.files.push({ file, status: "skipped-includes" });
33267
+ continue;
33268
+ }
33269
+ let canonical2;
33270
+ try {
33271
+ const raw = dump2(loadFile(file));
33272
+ if (dump2(load(raw)) !== raw) {
33273
+ result.files.push({ file, status: "unstable" });
33274
+ continue;
33275
+ }
33276
+ canonical2 = /^\s*metadata\s*\{/.test(src) ? raw : raw.replace(/^metadata \{\n(?: {2}\w+ ""\n)*\}\n+/, "");
33277
+ } catch {
33278
+ result.files.push({ file, status: "unstable" });
33279
+ continue;
33280
+ }
33281
+ if (canonical2 === src) {
33282
+ result.files.push({ file, status: "unchanged" });
33283
+ continue;
33284
+ }
33285
+ if (!check) {
33286
+ writeFileSync(file, canonical2);
33287
+ result.written += 1;
33288
+ }
33289
+ result.files.push({ file, status: "formatted" });
33290
+ }
33291
+ return result;
33292
+ }
33293
+
30549
33294
  // src/export/reqif.ts
30550
33295
  var REQIF_NAMESPACE = "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd";
30551
33296
  var REQIF_VERSION = "1.0";
@@ -31819,23 +34564,23 @@ function renderJsonLd(prefixes, triples) {
31819
34564
 
31820
34565
  // src/export/retrieval.ts
31821
34566
  import { createHash } from "node:crypto";
31822
- import { readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync3 } from "node:fs";
31823
- import { join as join6, relative } from "node:path";
34567
+ import { readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
34568
+ import { join as join7, relative } from "node:path";
31824
34569
 
31825
34570
  // src/export/unitsdb.ts
31826
- import { existsSync as existsSync6, readFileSync as readFileSync6 } from "node:fs";
31827
- import { join as join5 } from "node:path";
34571
+ import { existsSync as existsSync6, readFileSync as readFileSync7 } from "node:fs";
34572
+ import { join as join6 } from "node:path";
31828
34573
  function loadUnitsDb(dir) {
31829
34574
  if (!dir) {
31830
34575
  return null;
31831
34576
  }
31832
34577
  try {
31833
34578
  const entries = [];
31834
- const jsonPath = join5(dir, "units.json");
34579
+ const jsonPath = join6(dir, "units.json");
31835
34580
  if (!existsSync6(jsonPath)) {
31836
34581
  return null;
31837
34582
  }
31838
- const parsed = JSON.parse(readFileSync6(jsonPath, "utf8")).units;
34583
+ const parsed = JSON.parse(readFileSync7(jsonPath, "utf8")).units;
31839
34584
  if (!Array.isArray(parsed)) {
31840
34585
  return null;
31841
34586
  }
@@ -32066,12 +34811,12 @@ function retrievalDigest(value) {
32066
34811
  return createHash("sha256").update(canonicalJson(value), "utf8").digest("hex");
32067
34812
  }
32068
34813
  function* walkPackage(dir) {
32069
- for (const entry of readdirSync4(dir).sort()) {
34814
+ for (const entry of readdirSync5(dir).sort()) {
32070
34815
  if (entry === ".DS_Store") {
32071
34816
  continue;
32072
34817
  }
32073
- const p = join6(dir, entry);
32074
- if (statSync3(p).isDirectory()) {
34818
+ const p = join7(dir, entry);
34819
+ if (statSync4(p).isDirectory()) {
32075
34820
  yield* walkPackage(p);
32076
34821
  } else {
32077
34822
  yield p;
@@ -32083,7 +34828,7 @@ function packageSourceHash(dir) {
32083
34828
  for (const file of walkPackage(dir)) {
32084
34829
  h.update(relative(dir, file));
32085
34830
  h.update("\0");
32086
- h.update(createHash("sha256").update(readFileSync7(file)).digest());
34831
+ h.update(createHash("sha256").update(readFileSync8(file)).digest());
32087
34832
  h.update("\n");
32088
34833
  }
32089
34834
  return h.digest("hex");
@@ -32339,6 +35084,9 @@ function retrievalFacet(unit, pkg) {
32339
35084
  facet[`app_${dim}_match`] = match;
32340
35085
  }
32341
35086
  }
35087
+ if ((unit.method_refs ?? []).length > 0) {
35088
+ facet.method_refs = unit.method_refs.join("|");
35089
+ }
32342
35090
  return facet;
32343
35091
  }
32344
35092
  function resolveTextAddress(address, elementIds) {
@@ -32483,11 +35231,34 @@ function requirementUnit(r) {
32483
35231
  collectClauses(r)
32484
35232
  );
32485
35233
  }
35234
+ function processUnit(pr) {
35235
+ const steps = pr.steps ?? [];
35236
+ const calls = steps.map((s) => {
35237
+ const st = s;
35238
+ const call = st.calls || st.signatureBlock?.match(/\bcalls +([\w:/.-]+)/)?.[1] || "";
35239
+ return call ? { id: st.id ?? "", calls: call } : null;
35240
+ }).filter((s) => s !== null);
35241
+ return assemble(
35242
+ {
35243
+ id: pr.id,
35244
+ kind: "process",
35245
+ ...present(pr.name) ? { name: pr.name } : {},
35246
+ ...present(pr.summary) ? { statement: pr.summary } : {},
35247
+ ...calls.length > 0 ? { calls } : {}
35248
+ },
35249
+ collectClauses(pr)
35250
+ );
35251
+ }
32486
35252
  function conformanceTestUnit(t) {
32487
35253
  const payload = {
32488
35254
  ...present(t.kind) ? { test_kind: t.kind } : {},
32489
35255
  ...present(t.methodRef) ? { method_ref: t.methodRef } : {}
32490
35256
  };
35257
+ const methodRefs = [
35258
+ ...new Set(
35259
+ [t.methodRef, ...(t.requiredCompetence ?? []).map((rc) => rc.methodRef)].filter((m) => present(m)).map((m) => m)
35260
+ )
35261
+ ].sort();
32491
35262
  const decision = acceptanceDecisionOf(t.acceptance);
32492
35263
  const criteria = testAcceptanceCriteriaOf(t);
32493
35264
  return assemble(
@@ -32515,6 +35286,7 @@ function conformanceTestUnit(t) {
32515
35286
  }))
32516
35287
  } : {},
32517
35288
  ...presentList(t.dependencies) ? { dependencies: t.dependencies } : {},
35289
+ ...methodRefs.length > 0 ? { method_refs: methodRefs } : {},
32518
35290
  ...Object.keys(payload).length > 0 ? { payload } : {}
32519
35291
  },
32520
35292
  collectClauses(t)
@@ -32946,6 +35718,9 @@ function exportStandardRetrieval(standard, options = {}) {
32946
35718
  for (const t of standard.conformanceTests ?? []) {
32947
35719
  push(conformanceTestUnit(t), t.id);
32948
35720
  }
35721
+ for (const pr of standard.processes ?? []) {
35722
+ push(processUnit(pr), pr.id);
35723
+ }
32949
35724
  for (const t of standard.terms ?? []) {
32950
35725
  push(termUnit(t, pkg.base_urn), t.id);
32951
35726
  }
@@ -33256,8 +36031,8 @@ function exportPackageImpact(dir) {
33256
36031
  }
33257
36032
 
33258
36033
  // src/export/cddal.ts
33259
- import { readFileSync as readFileSync8, readdirSync as readdirSync5 } from "node:fs";
33260
- import { basename, join as join7, resolve as resolve5 } from "node:path";
36034
+ import { readFileSync as readFileSync9, readdirSync as readdirSync6 } from "node:fs";
36035
+ import { basename, join as join8, resolve as resolve5 } from "node:path";
33261
36036
  var CDDAL_PROJECTION_VERSION = "primmel-cddal/1";
33262
36037
  function escapeCddalString(s) {
33263
36038
  return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
@@ -33403,23 +36178,23 @@ function projectCddal(model, packageId, l10n = /* @__PURE__ */ new Map()) {
33403
36178
  }
33404
36179
  function exportPackageCddal(dir) {
33405
36180
  const model = loadPackage(dir);
33406
- const l10nFiles = readdirSync5(dir).filter((e) => /^l10n\.[^/]+\.prl$/.test(e)).map((e) => join7(dir, e));
33407
- const l10n = readL10n(l10nFiles, (p) => readFileSync8(p, "utf8"));
36181
+ const l10nFiles = readdirSync6(dir).filter((e) => /^l10n\.[^/]+\.prl$/.test(e)).map((e) => join8(dir, e));
36182
+ const l10n = readL10n(l10nFiles, (p) => readFileSync9(p, "utf8"));
33408
36183
  return projectCddal(model, basename(resolve5(dir)), l10n);
33409
36184
  }
33410
36185
 
33411
36186
  // src/package-diff.ts
33412
- import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync9 } from "fs";
33413
- import { join as join8 } from "path";
36187
+ import { existsSync as existsSync7, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "fs";
36188
+ import { join as join9 } from "path";
33414
36189
  function packageMappings(dir, standard) {
33415
36190
  const profiles = [...standard.mapProfiles ?? []];
33416
36191
  if (existsSync7(dir)) {
33417
- for (const entry of readdirSync6(dir).sort()) {
36192
+ for (const entry of readdirSync7(dir).sort()) {
33418
36193
  if (!entry.endsWith(".prm")) {
33419
36194
  continue;
33420
36195
  }
33421
36196
  profiles.push(
33422
- ...prmToMapProfiles(loadPrm(readFileSync9(join8(dir, entry), "utf8")))
36197
+ ...prmToMapProfiles(loadPrm(readFileSync10(join9(dir, entry), "utf8")))
33423
36198
  );
33424
36199
  }
33425
36200
  }
@@ -33428,17 +36203,17 @@ function packageMappings(dir, standard) {
33428
36203
  }
33429
36204
  function packageClauseTexts(dir) {
33430
36205
  const out = /* @__PURE__ */ new Map();
33431
- const prdDir = join8(dir, "sources-prd");
36206
+ const prdDir = join9(dir, "sources-prd");
33432
36207
  if (!existsSync7(prdDir)) {
33433
36208
  return out;
33434
36209
  }
33435
- for (const entry of readdirSync6(prdDir).sort()) {
36210
+ for (const entry of readdirSync7(prdDir).sort()) {
33436
36211
  if (!entry.endsWith(".sentences.json")) {
33437
36212
  continue;
33438
36213
  }
33439
36214
  let payload;
33440
36215
  try {
33441
- payload = JSON.parse(readFileSync9(join8(prdDir, entry), "utf8"));
36216
+ payload = JSON.parse(readFileSync10(join9(prdDir, entry), "utf8"));
33442
36217
  } catch {
33443
36218
  continue;
33444
36219
  }
@@ -33491,15 +36266,15 @@ var DIFF_USAGE = "Usage: primmel diff [--json] [--exit-code] [--compare-texts] [
33491
36266
  var EXPORT_USAGE = "Usage: primmel export reqif|rdf|retrieval|impact|cddal <package-dir> [--out <file>] [--format turtle|jsonld]";
33492
36267
  function readablePackageDirProblem(target, needsManifest) {
33493
36268
  try {
33494
- if (!statSync4(target).isDirectory()) {
36269
+ if (!statSync5(target).isDirectory()) {
33495
36270
  return "not a directory";
33496
36271
  }
33497
- readdirSync7(target);
36272
+ readdirSync8(target);
33498
36273
  } catch (e) {
33499
36274
  const err = e;
33500
36275
  return err.code === "ENOENT" ? "no such directory" : err.message;
33501
36276
  }
33502
- if (needsManifest && !existsSync8(join9(target, "package.primmel"))) {
36277
+ if (needsManifest && !existsSync8(join10(target, "package.primmel"))) {
33503
36278
  return "no package.primmel found";
33504
36279
  }
33505
36280
  return null;
@@ -33725,7 +36500,7 @@ function exportCli(args2) {
33725
36500
  const out = values.get("--out");
33726
36501
  if (out !== void 0) {
33727
36502
  try {
33728
- writeFileSync(out, document);
36503
+ writeFileSync2(out, document);
33729
36504
  } catch (e) {
33730
36505
  console.error(`cannot write ${out}: ${e.message}`);
33731
36506
  process.exit(1);
@@ -33736,6 +36511,32 @@ function exportCli(args2) {
33736
36511
  }
33737
36512
  process.exit(0);
33738
36513
  }
36514
+ function fmtCli(argv) {
36515
+ const check = argv.includes("--check");
36516
+ const rest = argv.filter((a) => a !== "--check");
36517
+ const dir = rest[rest.length - 1];
36518
+ if (!dir || !existsSync8(dir)) {
36519
+ console.error(`cannot read package at ${dir || "(none)"}: no such directory`);
36520
+ process.exit(2);
36521
+ }
36522
+ let result;
36523
+ try {
36524
+ result = fmtPackage(dir, check);
36525
+ } catch (e) {
36526
+ console.error(`cannot format package at ${dir}: ${e.message}`);
36527
+ process.exit(2);
36528
+ }
36529
+ for (const f of result.files) {
36530
+ const label = f.file.startsWith(dir + "/") ? f.file.slice(dir.length + 1) : f.file;
36531
+ const note = f.status === "formatted" ? check ? "would reformat" : "formatted" : f.status === "unchanged" ? "ok" : f.status === "unstable" ? "UNSTABLE \u2014 does not round-trip; left as-is" : "skipped (includes)";
36532
+ console.log(` ${label}: ${note}`);
36533
+ }
36534
+ const unstable = result.files.filter((f) => f.status === "unstable").length;
36535
+ console.log(
36536
+ `fmt: ${result.files.length} files, ${check ? result.files.filter((f) => f.status === "formatted").length + " would reformat" : result.written + " written"}, ${unstable} unstable`
36537
+ );
36538
+ process.exit(unstable > 0 ? 2 : check && result.files.some((f) => f.status === "formatted") ? 1 : 0);
36539
+ }
33739
36540
  var args = process.argv.slice(2);
33740
36541
  if (args[0] === "diff") {
33741
36542
  diffCli(args.slice(1));
@@ -33743,6 +36544,12 @@ if (args[0] === "diff") {
33743
36544
  checkCli(args.slice(1));
33744
36545
  } else if (args[0] === "export") {
33745
36546
  exportCli(args.slice(1));
36547
+ } else if (args[0] === "fmt") {
36548
+ fmtCli(args.slice(1));
33746
36549
  } else {
33747
36550
  checkCli(args);
33748
36551
  }
36552
+ //! The Primmel expression language: the lexer, the precedence parser, and
36553
+ //! the AST. The machine-executable core — first-class syntax, never a
36554
+ //! quoted string. The identifiers resolve against the caller's scope (the
36555
+ //! argument bindings); the unbound names surface at parse time.