@uipath/case-tool 1.202.0 → 1.203.0-preview.160

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 (90) hide show
  1. package/dist/THIRD-PARTY-NOTICES.md +172 -3
  2. package/dist/{authoring-e757p9dq.js → authoring-kngaggwm.js} +42 -4
  3. package/dist/{case-api-42s4mbpn.js → case-api-v6cjyrfw.js} +8 -8
  4. package/dist/case-bindings-service-1wxfghzd.js +240 -0
  5. package/dist/case-debug-studio-web-service-0624c07c.js +133 -0
  6. package/dist/case-format-service-q345a2fd.js +84 -0
  7. package/dist/{case-pack-service-8exkecnd.js → case-pack-service-29rza2q2.js} +61 -11
  8. package/dist/{case-validate-service-xvxkr026.js → case-validate-service-e06varbt.js} +1422 -40
  9. package/dist/{connector-enrichment-service-xq9xtz95.js → connector-enrichment-service-2pes4b1b.js} +20 -20
  10. package/dist/{connector-lookup-service-bk1wscyr.js → connector-lookup-service-2bkybhkf.js} +7 -7
  11. package/dist/{connector-task-spec-0g34na74.js → connector-task-spec-q59xmzm0.js} +24 -24
  12. package/dist/{de-7XQXX2DK-tqdy5n2b.js → de-FGHEJRCI-rv513mfh.js} +153 -9
  13. package/dist/{de-5KVP66U6-1bnf4zt5.js → de-MUJPA4EB-dpg7t2rw.js} +15 -3
  14. package/dist/{debug-service-f6t4ntmg.js → debug-service-8x087xxt.js} +2 -2
  15. package/dist/{index-j3xb87ag.js → embedded-file-reader-0sjt4nkj.js} +96 -16641
  16. package/dist/{en-5ZGC5VQ3-h581y30k.js → en-BWGKA5OE-1qkvb9rn.js} +140 -2
  17. package/dist/{en-X3S6IZ5J-nhkg6pwn.js → en-FBPVNKFN-dqt573xn.js} +29 -3
  18. package/dist/{enrichment-service-k1zhkzgr.js → enrichment-service-7vbxcwge.js} +7 -7
  19. package/dist/{es-VFPNVMP5-bx2c337j.js → es-7SE7HX2X-8yh1aj2y.js} +15 -3
  20. package/dist/{es-ZGCPPOME-8gazspjj.js → es-KR3ZSNMP-84zphx0x.js} +153 -9
  21. package/dist/{es-MX-XAVLOQW3-q00km2y7.js → es-MX-2MYFZU7X-3rek4r73.js} +15 -3
  22. package/dist/{es-MX-U2VN3SZW-anynsmd8.js → es-MX-XXZJGC4R-2mr8jtgm.js} +153 -9
  23. package/dist/first-party-service-srxaftkn.js +27 -0
  24. package/dist/{fr-E5MDO4EG-c3mkty2t.js → fr-MDFKNZ4C-h4a122k9.js} +15 -3
  25. package/dist/{fr-T3G5GZCT-y3f7xb1q.js → fr-Y6NPVODW-8vr1ja4b.js} +153 -9
  26. package/dist/{index-f0rf4m8p.js → index-8yv94z7r.js} +6 -4
  27. package/dist/{index-kwxe1vep.js → index-fz4ttsde.js} +16 -4
  28. package/dist/index-jxj2jz45.js +16742 -0
  29. package/dist/index-kmp9fmhb.js +25 -0
  30. package/dist/index.js +10 -10
  31. package/dist/{input-reader-vgsdjgst.js → input-reader-pnh948bq.js} +1 -1
  32. package/dist/{ja-BI5K3JDZ-77zat4z2.js → ja-Q5PXKJ2V-p4msxzjd.js} +153 -9
  33. package/dist/{ja-DPO5PPLO-mysfmznx.js → ja-UTQEAP34-8e0q6swp.js} +15 -3
  34. package/dist/{known-types-qryebm95.js → known-types-mn8xn36b.js} +4 -4
  35. package/dist/{ko-ITOPNIYI-hmxd2asd.js → ko-AXCHW2OK-askct7f6.js} +15 -3
  36. package/dist/{ko-JOBF5V7N-4bv0mjje.js → ko-AYBDSRZG-41mdmsg1.js} +153 -9
  37. package/dist/{node-strategy-0267x5e5.js → node-strategy-gc4sg6a2.js} +4 -4
  38. package/dist/{node-sync-service-ac8rzgnj.js → node-sync-service-9d0dqz4z.js} +12 -14
  39. package/dist/{packager-tool-5yw9xatr.js → packager-tool-052kvydg.js} +1 -1
  40. package/dist/{packager-tool-3tfbb641.js → packager-tool-32jxda3r.js} +213 -51
  41. package/dist/packager-tool-53w8skv5.js +262 -0
  42. package/dist/{packager-tool-w0209wf4.js → packager-tool-61hxhgeg.js} +1 -1
  43. package/dist/{packager-tool-58q3tvh7.js → packager-tool-7q6z6npd.js} +166 -28
  44. package/dist/packager-tool-83qnybab.js +1564 -0
  45. package/dist/{packager-tool-eh50gcdk.js → packager-tool-8q7vzh65.js} +5 -4
  46. package/dist/{packager-tool-8rf8qda5.js → packager-tool-adcaxdhs.js} +15 -5
  47. package/dist/{packager-tool-933n6t8x.js → packager-tool-af2s79jb.js} +6 -6
  48. package/dist/{packager-tool-sk2b33km.js → packager-tool-b6368khs.js} +10 -9
  49. package/dist/{packager-tool-d73376xs.js → packager-tool-cg2j4rma.js} +8 -8
  50. package/dist/packager-tool-d4sjk46c.js +88 -0
  51. package/dist/{packager-tool-a42jnpy5.js → packager-tool-d88rqwk8.js} +29 -3
  52. package/dist/packager-tool-dd8bq6az.js +8462 -0
  53. package/dist/packager-tool-gdtpsdn7.js +342 -0
  54. package/dist/{packager-tool-v60h8pvv.js → packager-tool-hrdan5ms.js} +1 -1
  55. package/dist/{packager-tool-bmn50g7v.js → packager-tool-hz1mz8fs.js} +1 -1
  56. package/dist/{packager-tool-v0vdet53.js → packager-tool-jf4hmztd.js} +10 -13
  57. package/dist/{packager-tool-c23zrhj8.js → packager-tool-jysvpt8p.js} +2 -2
  58. package/dist/{packager-tool-jhdf8gt1.js → packager-tool-kkxhc0fp.js} +13554 -8844
  59. package/dist/{packager-tool-4knkebkr.js → packager-tool-kpcjnxd1.js} +269 -23
  60. package/dist/{packager-tool-nx0j1294.js → packager-tool-rhkk0pta.js} +31 -30
  61. package/dist/{packager-tool-d128hs55.js → packager-tool-wefb1zw3.js} +1 -1
  62. package/dist/{packager-tool-3kbkkv2a.js → packager-tool-x4vxexvk.js} +11 -11
  63. package/dist/{packager-tool-dqs5qy9s.js → packager-tool-yrsrzz1a.js} +134 -19
  64. package/dist/packager-tool.js +5 -1501
  65. package/dist/{project-artifacts-43c2ynd9.js → project-artifacts-8snev67g.js} +1 -1
  66. package/dist/{pt-YI4VE4YQ-wdkn2dcf.js → pt-3DIO5QWG-59b3f4bc.js} +15 -3
  67. package/dist/{pt-BR-7DYX2YPT-fqxqzqtf.js → pt-BR-TKHNHMET-sn91xyq0.js} +153 -9
  68. package/dist/{pt-BR-BXURWX4W-bwfcwhk1.js → pt-BR-Y6K6XHXK-mp3hwhw1.js} +15 -3
  69. package/dist/{pt-HTXGGX6Y-97t21dty.js → pt-ROXU257Y-2f6bxev4.js} +153 -9
  70. package/dist/{resourcesSyncService-7ampdrez.js → resourcesSyncService-5bq0j9wf.js} +20 -20
  71. package/dist/{ro-KTNQ3MNU-y08n1x5g.js → ro-AVAWPKOO-b89pw79r.js} +153 -9
  72. package/dist/{ro-RKXZUG7Z-nndrrsq7.js → ro-BWR3ONRR-vzx3hy8a.js} +15 -3
  73. package/dist/ru-WBLQ5B2U-s4em88p0.js +10 -0
  74. package/dist/sdd-lookup-x08j9g9m.js +48 -0
  75. package/dist/{strict-case-rules-303vjvas.js → strict-case-rules-x6t0vb40.js} +141 -109
  76. package/dist/strict-sdd-audit-8e2fh9jg.js +2520 -0
  77. package/dist/tool.js +9 -9
  78. package/dist/{tr-AA6O2WSR-86ba4bdf.js → tr-5IIHSFW5-hw4cewew.js} +15 -3
  79. package/dist/{tr-XHSSPNK7-cmqyc4wd.js → tr-JMIP7ZSL-c39b6pe4.js} +153 -9
  80. package/dist/{trigger-enrichment-service-cg99dk1f.js → trigger-enrichment-service-kkh3197w.js} +24 -24
  81. package/dist/{zh-CN-2EHQT23P-mr63c4xz.js → zh-CN-IFFXSEJS-9wm9gmrv.js} +153 -9
  82. package/dist/{zh-CN-R2KLHXQV-agqr45ds.js → zh-CN-R2KU4U5L-tc1hat59.js} +15 -3
  83. package/dist/{zh-TW-RJGCQANM-w0x3qc1p.js → zh-TW-GNKMELBF-j674515r.js} +15 -3
  84. package/dist/{zh-TW-MGZCE5BT-c4ekmrz9.js → zh-TW-IYBNYAMG-8727c7v2.js} +153 -9
  85. package/package.json +3 -2
  86. package/dist/case-debug-studio-web-service-npcw81ay.js +0 -335
  87. package/dist/packager-tool-134mvmcm.js +0 -3040
  88. package/dist/packager-tool-ty1t2byf.js +0 -27
  89. package/dist/ru-WBLQ5B2U-8r3c7v6d.js +0 -10
  90. package/dist/strict-sdd-audit-qdmc9e1y.js +0 -1024
@@ -1,1024 +0,0 @@
1
- import {
2
- isAnyTriggerNode,
3
- isStageNode
4
- } from "./packager-tool-sv0d6wb6.js";
5
- import"./packager-tool-1yh8g550.js";
6
-
7
- // src/services/strict-sdd-audit.ts
8
- var isDigit = (ch) => ch >= "0" && ch <= "9";
9
- var isLowerLetter = (ch) => ch >= "a" && ch <= "z";
10
- var isUpperLetter = (ch) => ch >= "A" && ch <= "Z";
11
- var isLetter = (ch) => isLowerLetter(ch) || isUpperLetter(ch);
12
- var isWordChar = (ch) => isLetter(ch) || isDigit(ch) || ch === "_";
13
- var isSlugChar = (ch) => isDigit(ch) || isLowerLetter(ch) || ch === "-" || ch === "_";
14
- var readHeading = (line) => {
15
- let level = 0;
16
- while (level < line.length && line[level] === "#")
17
- level += 1;
18
- if (level === 0 || level > 6)
19
- return;
20
- const rest = line.slice(level);
21
- if (!rest.startsWith(" ") && !rest.startsWith("\t"))
22
- return;
23
- return { level, title: rest.trim() };
24
- };
25
- var firstIndexOfEither = (text, a, b) => {
26
- const first = text.indexOf(a);
27
- const second = text.indexOf(b);
28
- if (first === -1)
29
- return second;
30
- if (second === -1)
31
- return first;
32
- return Math.min(first, second);
33
- };
34
- var readStageHeading = (title) => {
35
- const words = title.trim().split(" ").filter((w) => w !== "");
36
- const at = words.findIndex((w) => w.toLowerCase().startsWith("stage"));
37
- if (at === -1 || at > 1)
38
- return;
39
- let rest = words.slice(at).join(" ");
40
- rest = rest.slice("stage".length);
41
- const separator = firstIndexOfEither(rest, ":", ".");
42
- if (separator === -1)
43
- return;
44
- const between = rest.slice(0, separator).trim();
45
- if (between !== "" && ![...between].every(isDigit))
46
- return;
47
- const name = rest.slice(separator + 1).trim();
48
- return name === "" ? undefined : name;
49
- };
50
- var readTaskHeading = (title) => {
51
- const text = title.trim();
52
- if (!text.toLowerCase().startsWith("task "))
53
- return;
54
- let rest = text.slice("task ".length).trimStart();
55
- if (rest.length > 0 && rest[0] >= "A" && rest[0] <= "Z")
56
- rest = rest.slice(1);
57
- let at = 0;
58
- while (at < rest.length && (isDigit(rest[at]) || rest[at] === "."))
59
- at += 1;
60
- if (at === 0)
61
- return;
62
- const marker = rest.slice(0, at);
63
- let tail = rest.slice(at);
64
- if (marker.endsWith("."))
65
- tail = `.${tail}`;
66
- tail = tail.trimStart();
67
- if (!tail.startsWith(":") && !tail.startsWith("."))
68
- return;
69
- const name = tail.slice(1).trim();
70
- return name === "" ? undefined : name;
71
- };
72
- var isSeparatorCell = (cell) => {
73
- let body = cell;
74
- if (body.startsWith(":"))
75
- body = body.slice(1);
76
- if (body.endsWith(":"))
77
- body = body.slice(0, -1);
78
- return body.length >= 2 && [...body].every((ch) => ch === "-");
79
- };
80
- var hasUnresolvedMarker = (text) => text.toLowerCase().includes("<unresolved");
81
- var withoutSectionNumber = (key) => {
82
- const words = key.split(" ");
83
- let at = 0;
84
- if (words[at] === "section")
85
- at += 1;
86
- const looksNumbered = (word) => {
87
- if (!word)
88
- return false;
89
- let i = 0;
90
- if (isLowerLetter(word[i]))
91
- i += 1;
92
- const start = i;
93
- while (i < word.length && isDigit(word[i]))
94
- i += 1;
95
- if (i === start)
96
- return false;
97
- if (i < word.length && isLowerLetter(word[i]))
98
- i += 1;
99
- return i === word.length;
100
- };
101
- if (!looksNumbered(words[at]))
102
- return key;
103
- at += 1;
104
- while (looksNumbered(words[at]))
105
- at += 1;
106
- return words.slice(at).join(" ");
107
- };
108
- var TOPIC_WORDS = ["conditions", "variables", "triggers", "sla"];
109
- var withoutTrailingSlug = (text) => {
110
- const trimmed = text.trimEnd();
111
- if (!trimmed.endsWith(")"))
112
- return text;
113
- const open = trimmed.lastIndexOf("(");
114
- if (open === -1)
115
- return text;
116
- let inner = trimmed.slice(open + 1, -1).trim();
117
- if (inner.startsWith("`") && inner.endsWith("`") && inner.length >= 2) {
118
- inner = inner.slice(1, -1);
119
- }
120
- if (inner === "" || ![...inner].every(isSlugChar))
121
- return text;
122
- return trimmed.slice(0, open).trimEnd();
123
- };
124
- var PLACEHOLDER_CELLS = ["", "-", "—", "–", "n/a", "na", "none", "tbd"];
125
- var CASE_EXIT_HEADINGS = [
126
- "Case Exit Conditions",
127
- "Case Completion Conditions"
128
- ];
129
- var CASE_TRIGGER_HEADINGS = ["Case Triggers", "Triggers"];
130
- var CASE_SLA_HEADINGS = ["Case-Level SLA Escalation Rules"];
131
- var CASE_VARIABLE_HEADINGS = ["Case Variables"];
132
- var STAGE_ENTRY_HEADINGS = ["Stage Entry Conditions"];
133
- var STAGE_EXIT_HEADINGS = [
134
- "Stage Exit Conditions",
135
- "Stage Completion Conditions"
136
- ];
137
- var STAGE_SLA_HEADINGS = ["Stage SLA"];
138
- var STAGE_TASK_HEADINGS = ["Tasks"];
139
- var VARIABLE_GROUPS = ["inputs", "outputs", "inputOutputs"];
140
- var VARIABLE_PLACEMENT = new Map([
141
- ["in", ["inputs", "inputOutputs"]],
142
- ["out", ["outputs", "inputOutputs"]],
143
- ["variable", ["inputOutputs"]]
144
- ]);
145
- var QUOTE_CHARS = new Set(["`", '"', "“", "”", "‘", "’", " "]);
146
- var trimQuotes = (text) => {
147
- let start = 0;
148
- let end = text.length;
149
- while (start < end && QUOTE_CHARS.has(text[start]))
150
- start += 1;
151
- while (end > start && QUOTE_CHARS.has(text[end - 1]))
152
- end -= 1;
153
- return text.slice(start, end);
154
- };
155
- var normAnnotationless = (value) => {
156
- const text = String(value ?? "").trim();
157
- if (!text.endsWith(")"))
158
- return norm(text);
159
- const open = text.lastIndexOf("(");
160
- return open === -1 ? norm(text) : norm(text.slice(0, open));
161
- };
162
- var norm = (value) => {
163
- const text = trimQuotes(withoutTrailingSlug(String(value ?? "").trim()));
164
- const words = [];
165
- let word = "";
166
- for (const ch of text.toLowerCase()) {
167
- if (isLowerLetter(ch) || isDigit(ch))
168
- word += ch;
169
- else if (word !== "") {
170
- words.push(word);
171
- word = "";
172
- }
173
- }
174
- if (word !== "")
175
- words.push(word);
176
- return words.join(" ");
177
- };
178
- var headingKey = (title) => withoutSectionNumber(norm(title));
179
- var headingIs = (title, accepted) => accepted.some((a) => headingKey(a) === headingKey(title));
180
- var topicOf = (title) => {
181
- const key = headingKey(title);
182
- const words = key.split(" ");
183
- if (words.some((w) => w === "task" || w === "tasks"))
184
- return "tasks";
185
- const last = words.at(-1);
186
- return TOPIC_WORDS.find((topic) => topic === last);
187
- };
188
- var isBlank = (cell) => PLACEHOLDER_CELLS.map(norm).includes(norm(cell));
189
- var sectionBlocks = (text) => {
190
- const heads = [];
191
- let offset = 0;
192
- for (const line of text.split(`
193
- `)) {
194
- const heading = readHeading(line);
195
- if (heading) {
196
- heads.push({
197
- level: heading.level,
198
- title: heading.title,
199
- start: offset,
200
- at: offset + line.length
201
- });
202
- }
203
- offset += line.length + 1;
204
- }
205
- return heads.map((head, index) => {
206
- let end = text.length;
207
- for (const later of heads.slice(index + 1)) {
208
- if (later.level <= head.level) {
209
- end = later.start;
210
- break;
211
- }
212
- }
213
- return {
214
- level: head.level,
215
- title: head.title,
216
- body: text.slice(head.at, end)
217
- };
218
- });
219
- };
220
- var firstTable = (block) => {
221
- let header = [];
222
- const rows = [];
223
- for (const line of block.split(`
224
- `)) {
225
- const stripped = line.trim();
226
- if (!stripped.startsWith("|")) {
227
- if (header.length > 0 && rows.length > 0)
228
- break;
229
- continue;
230
- }
231
- let inner = stripped;
232
- if (inner.startsWith("|"))
233
- inner = inner.slice(1);
234
- if (inner.endsWith("|"))
235
- inner = inner.slice(0, -1);
236
- const cells = inner.split("|").map((c) => c.trim());
237
- if (cells.length > 0 && cells.filter((c) => c !== "").every(isSeparatorCell)) {
238
- continue;
239
- }
240
- if (header.length === 0)
241
- header = cells;
242
- else
243
- rows.push(cells);
244
- }
245
- return { header, rows };
246
- };
247
- var columnIndex = (header, ...names) => {
248
- const wanted = new Set(names.map(norm));
249
- const found = header.findIndex((c) => wanted.has(norm(c)));
250
- return found === -1 ? undefined : found;
251
- };
252
- var cellAt = (row, index) => index !== undefined && index < row.length ? row[index] : "";
253
- var stripTicks = (value) => {
254
- let text = value;
255
- if (text.startsWith("`"))
256
- text = text.slice(1);
257
- if (text.endsWith("`"))
258
- text = text.slice(0, -1);
259
- return text;
260
- };
261
- var field = (block, label) => {
262
- const wanted = label.toLowerCase();
263
- for (const line of block.split(`
264
- `)) {
265
- const text = line.trim();
266
- if (!text.startsWith("**"))
267
- continue;
268
- const close = text.indexOf("**", 2);
269
- if (close === -1)
270
- continue;
271
- let name = text.slice(2, close).trim().toLowerCase();
272
- if (name.endsWith(":"))
273
- name = name.slice(0, -1);
274
- if (name !== wanted)
275
- continue;
276
- return text.slice(close + 2).trim();
277
- }
278
- return;
279
- };
280
- var noNameColumnNote = (title, wanted, header) => `section "${title}": the table has rows but no ${wanted.join("/")} ` + `column (header: ${header.join(" | ") || "<none>"}) — every row is ` + "skipped, so the section contributes nothing to audit";
281
- var capitalize = (text) => text.charAt(0).toUpperCase() + text.slice(1);
282
- var noCategoryColumnNote = (title, header) => `section "${title}": the table has rows but no Category column ` + `(header: ${header.join(" | ") || "<none>"}) — no row can be checked ` + "for `variables` group placement, so a formal argument missing half its " + "pair passes";
283
- var unrecognizedHeadingNote = (title, level) => `heading "${title}" (level ${level}) reads like an audited section but ` + "matches no accepted spelling — rename it to one of the canonical " + "headings, or the checks it feeds are skipped";
284
- var detailEntryRows = (block) => {
285
- let rows = 0;
286
- for (const sub of sectionBlocks(block)) {
287
- if (norm(sub.title).startsWith(norm("Entry Condition"))) {
288
- rows = firstTable(sub.body).rows.length;
289
- }
290
- }
291
- const lines = block.split(`
292
- `);
293
- const isInlineLabel = (line) => line.trim().startsWith("**") && norm(line.replaceAll("*", "")).startsWith(norm("Entry Condition"));
294
- const at = lines.findIndex(isInlineLabel);
295
- if (at === -1)
296
- return rows;
297
- const tail = [];
298
- for (const line of lines.slice(at + 1)) {
299
- const text = line.trim();
300
- if (text.startsWith("**") || readHeading(text))
301
- break;
302
- tail.push(line);
303
- }
304
- return Math.max(rows, firstTable(tail.join(`
305
- `)).rows.length);
306
- };
307
- var afterBoldLabel = (block, label) => {
308
- const opener = `**${label}`;
309
- const hits = [];
310
- let at = block.indexOf(opener);
311
- while (at !== -1) {
312
- const from = at + opener.length;
313
- if (!isWordChar(block.charAt(from)))
314
- hits.push({ at, from });
315
- at = block.indexOf(opener, from);
316
- }
317
- return hits.map(({ from }, index) => block.slice(from, hits[index + 1]?.at ?? block.length));
318
- };
319
- var isIdentifier = (text) => {
320
- const head = text.charAt(0);
321
- if (!isLetter(head) && head !== "_")
322
- return false;
323
- for (const ch of text.slice(1)) {
324
- if (!isWordChar(ch))
325
- return false;
326
- }
327
- return true;
328
- };
329
- var detailLiteralInputs = (block) => {
330
- const inputs = [];
331
- for (const sub of afterBoldLabel(block, "Inputs")) {
332
- const { header, rows } = firstTable(sub);
333
- const nameAt = columnIndex(header, "Name", "Input", "Field");
334
- const valueAt = columnIndex(header, "Binding / Value", "Binding", "Value");
335
- if (nameAt === undefined || valueAt === undefined)
336
- continue;
337
- for (const row of rows) {
338
- const name = stripTicks(cellAt(row, nameAt).trim());
339
- const raw = stripTicks(cellAt(row, valueAt).trim());
340
- if (!name || isBlank(name) || isBlank(raw))
341
- continue;
342
- if (raw.startsWith("=") || raw.startsWith("<-"))
343
- continue;
344
- inputs.push({ name, value: raw });
345
- }
346
- }
347
- return inputs;
348
- };
349
- var detailExtractRows = (block) => {
350
- const rows = [];
351
- for (const sub of afterBoldLabel(block, "Outputs")) {
352
- const { header, rows: tableRows } = firstTable(sub);
353
- const fieldAt = columnIndex(header, "Field", "Name", "Output");
354
- const bindingAt = columnIndex(header, "Binding / Value", "Binding", "Value");
355
- if (fieldAt === undefined || bindingAt === undefined)
356
- continue;
357
- for (const row of tableRows) {
358
- const field2 = stripTicks(cellAt(row, fieldAt).trim());
359
- const binding = stripTicks(cellAt(row, bindingAt).trim());
360
- if (!field2 || isBlank(field2) || !binding.startsWith("->"))
361
- continue;
362
- const variable = binding.slice(2).trim();
363
- if (!variable || isBlank(variable))
364
- continue;
365
- rows.push({ field: field2, variable });
366
- }
367
- }
368
- return rows;
369
- };
370
- var detailCustomRows = (block) => {
371
- const rows = [];
372
- for (const sub of afterBoldLabel(block, "Outputs")) {
373
- const { header, rows: tableRows } = firstTable(sub);
374
- const bindingAt = columnIndex(header, "Binding / Value", "Binding", "Value");
375
- if (bindingAt === undefined)
376
- continue;
377
- for (const row of tableRows) {
378
- const binding = stripTicks(cellAt(row, bindingAt).trim());
379
- const at = binding.indexOf("=");
380
- if (at <= 0)
381
- continue;
382
- const variable = binding.slice(0, at).trim();
383
- const expression = binding.slice(at + 1).trim();
384
- if (!isIdentifier(variable))
385
- continue;
386
- if (!expression || isBlank(expression))
387
- continue;
388
- rows.push({ variable, expression });
389
- }
390
- }
391
- return rows;
392
- };
393
- var readTaskDetail = (block) => {
394
- const identity = [
395
- field(block, "Resource Identity"),
396
- field(block, "Folder Path"),
397
- field(block, "Connection ID"),
398
- field(block, "Activity Type ID")
399
- ].filter((value) => !!value && !isBlank(value));
400
- return {
401
- type: stripTicks(field(block, "Type") ?? ""),
402
- resolvedResource: field(block, "Resolved Resource"),
403
- identityResolved: identity.length > 0 && !identity.some(hasUnresolvedMarker),
404
- entryRows: detailEntryRows(block),
405
- literalInputs: detailLiteralInputs(block),
406
- extractRows: detailExtractRows(block),
407
- customRows: detailCustomRows(block)
408
- };
409
- };
410
- var readTaskRows = (title, block, notes) => {
411
- const { header, rows } = firstTable(block);
412
- const wanted = ["Task Name", "Task", "Name"];
413
- const nameAt = columnIndex(header, ...wanted);
414
- if (rows.length > 0 && nameAt === undefined) {
415
- notes.push(noNameColumnNote(title, wanted, header));
416
- }
417
- const typeAt = columnIndex(header, "Type", "Task Type");
418
- const tasks = [];
419
- for (const row of rows) {
420
- const taskName = cellAt(row, nameAt);
421
- if (!taskName || isBlank(taskName))
422
- continue;
423
- tasks.push({
424
- name: stripTicks(taskName.trim()),
425
- type: stripTicks(cellAt(row, typeAt).trim()),
426
- literalInputs: [],
427
- extractRows: [],
428
- customRows: [],
429
- identityResolved: false,
430
- entryRows: 0
431
- });
432
- }
433
- return tasks;
434
- };
435
- var applyStageSection = (stage, title, block, notes) => {
436
- if (headingIs(title, STAGE_ENTRY_HEADINGS)) {
437
- stage.entryRows = firstTable(block).rows.length;
438
- } else if (headingIs(title, STAGE_EXIT_HEADINGS)) {
439
- stage.exitRows = firstTable(block).rows.length;
440
- } else if (headingIs(title, STAGE_SLA_HEADINGS)) {
441
- stage.hasSla = firstTable(block).rows.length > 0;
442
- } else if (headingIs(title, STAGE_TASK_HEADINGS)) {
443
- stage.tasks.push(...readTaskRows(title, block, notes));
444
- } else {
445
- return false;
446
- }
447
- return true;
448
- };
449
- var parseStage = (name, body, notes) => {
450
- const stage = {
451
- name: name.trim(),
452
- tasks: [],
453
- entryRows: 0,
454
- exitRows: 0,
455
- hasSla: false
456
- };
457
- const details = new Map;
458
- const stageNotes = [];
459
- const lookalikes = [];
460
- for (const { title, body: block, level } of sectionBlocks(body)) {
461
- if (level === 4) {
462
- if (applyStageSection(stage, title, block, stageNotes))
463
- continue;
464
- const topic = topicOf(title);
465
- if (topic === "conditions" || topic === "sla" || topic === "tasks") {
466
- lookalikes.push([title, topic]);
467
- }
468
- continue;
469
- }
470
- if (level !== 5)
471
- continue;
472
- const detailName = readTaskHeading(title);
473
- if (detailName !== undefined) {
474
- details.set(norm(detailName), readTaskDetail(block));
475
- }
476
- }
477
- for (const task of stage.tasks) {
478
- const detail = details.get(norm(task.name));
479
- if (!detail)
480
- continue;
481
- task.literalInputs = detail.literalInputs;
482
- task.extractRows = detail.extractRows;
483
- task.customRows = detail.customRows;
484
- task.resolvedResource = detail.resolvedResource;
485
- task.identityResolved = detail.identityResolved;
486
- task.entryRows = detail.entryRows;
487
- if (!task.type && detail.type)
488
- task.type = detail.type;
489
- }
490
- const empty = {
491
- conditions: !(stage.entryRows && stage.exitRows),
492
- sla: !stage.hasSla,
493
- tasks: stage.tasks.length === 0
494
- };
495
- for (const [title, topic] of lookalikes) {
496
- if (empty[topic])
497
- stageNotes.push(unrecognizedHeadingNote(title, 4));
498
- }
499
- if (details.size > 0 && stage.tasks.length === 0 && stageNotes.length === 0) {
500
- stageNotes.push(`${details.size} \`Task <n>.<m>:\` detail section(s) but no task ` + "row parsed — the `#### Tasks` table is missing or has no Task " + "Name column, so none of its tasks are audited");
501
- }
502
- notes.push(...stageNotes.map((note) => `stage "${stage.name}": ${note}`));
503
- return stage;
504
- };
505
- var applyCaseSection = (sdd, title, body) => {
506
- if (headingIs(title, CASE_EXIT_HEADINGS)) {
507
- sdd.caseExitRows = firstTable(body).rows.length;
508
- } else if (headingIs(title, CASE_TRIGGER_HEADINGS)) {
509
- sdd.triggers = firstTable(body).rows.length;
510
- } else if (headingIs(title, CASE_SLA_HEADINGS)) {
511
- sdd.caseSla = firstTable(body).rows.length > 0;
512
- } else if (headingIs(title, CASE_VARIABLE_HEADINGS)) {
513
- const { header, rows } = firstTable(body);
514
- const wanted = ["Name", "Variable", "Variable Name"];
515
- const nameAt = columnIndex(header, ...wanted);
516
- const categoryAt = columnIndex(header, "Category");
517
- if (rows.length > 0 && nameAt === undefined) {
518
- sdd.parseNotes.push(noNameColumnNote(title, wanted, header));
519
- } else if (rows.length > 0 && categoryAt === undefined) {
520
- sdd.parseNotes.push(noCategoryColumnNote(title, header));
521
- }
522
- for (const row of rows) {
523
- const name = cellAt(row, nameAt);
524
- if (name && !isBlank(name)) {
525
- sdd.variables.push(stripTicks(name.trim()));
526
- const category = norm(cellAt(row, categoryAt));
527
- if (VARIABLE_PLACEMENT.has(category)) {
528
- sdd.variableCategories.set(norm(name), category);
529
- }
530
- }
531
- }
532
- } else {
533
- return false;
534
- }
535
- return true;
536
- };
537
- var parseSdd = (text) => {
538
- const sdd = {
539
- stages: [],
540
- caseExitRows: 0,
541
- triggers: 0,
542
- variables: [],
543
- variableCategories: new Map,
544
- caseSla: false,
545
- parseNotes: []
546
- };
547
- const lookalikes = [];
548
- for (const { level, title, body } of sectionBlocks(text)) {
549
- if (level !== 3)
550
- continue;
551
- if (applyCaseSection(sdd, title, body))
552
- continue;
553
- const stageName = readStageHeading(title);
554
- if (stageName !== undefined) {
555
- sdd.stages.push(parseStage(stageName, body, sdd.parseNotes));
556
- continue;
557
- }
558
- const topic = topicOf(title);
559
- if (topic === "conditions" || topic === "variables" || topic === "triggers" || topic === "sla") {
560
- lookalikes.push([title, topic]);
561
- }
562
- }
563
- const empty = {
564
- conditions: !sdd.caseExitRows,
565
- variables: sdd.variables.length === 0,
566
- triggers: !sdd.triggers,
567
- sla: !sdd.caseSla
568
- };
569
- for (const [title, topic] of lookalikes) {
570
- if (empty[topic])
571
- sdd.parseNotes.push(unrecognizedHeadingNote(title, 3));
572
- }
573
- return sdd;
574
- };
575
- var asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
576
- var asArray = (value) => Array.isArray(value) ? value : [];
577
- var bindingId = (expression) => {
578
- if (typeof expression !== "string")
579
- return;
580
- const text = expression.trim();
581
- const prefix = "=bindings.";
582
- if (!text.startsWith(prefix))
583
- return;
584
- const id = text.slice(prefix.length);
585
- const isWordChar2 = (ch) => isDigit(ch) || ch === "_" || isLowerLetter(ch.toLowerCase());
586
- return id !== "" && [...id].every(isWordChar2) ? id : undefined;
587
- };
588
- var bindingDefault = (bindings, expression) => {
589
- const id = bindingId(expression);
590
- if (id === undefined)
591
- return;
592
- const binding = bindings.find((b) => b.id === id);
593
- const value = binding?.default;
594
- return typeof value === "string" ? value : undefined;
595
- };
596
- var readPlanTasks = (data, bindings) => {
597
- const tasks = [];
598
- for (const lane of asArray(data.tasks)) {
599
- for (const task of asArray(lane)) {
600
- const record = asRecord(task);
601
- if (!record)
602
- continue;
603
- const taskData = asRecord(record.data) ?? {};
604
- const name = (typeof record.displayName === "string" ? record.displayName : undefined) ?? (typeof record.label === "string" ? record.label : undefined) ?? bindingDefault(bindings, taskData.name);
605
- tasks.push({
606
- name,
607
- type: typeof record.type === "string" ? record.type : undefined,
608
- entry: asArray(record.entryConditions),
609
- data: taskData
610
- });
611
- }
612
- }
613
- return tasks;
614
- };
615
- var readPlanVariables = (doc) => {
616
- const variablesDoc = asRecord(doc.variables) ?? {};
617
- const variables = [];
618
- const variableGroups = {};
619
- for (const group of VARIABLE_GROUPS) {
620
- const names = [];
621
- for (const entry of asArray(variablesDoc[group])) {
622
- const name = asRecord(entry)?.name;
623
- if (typeof name === "string")
624
- names.push(name);
625
- }
626
- variableGroups[group] = new Set(names.map(norm));
627
- variables.push(...names);
628
- }
629
- return { variables, variableGroups };
630
- };
631
- var parseCaseplan = (doc) => {
632
- const bindings = asArray(doc.bindings).map(asRecord).filter((b) => b !== undefined);
633
- const metadata = asRecord(doc.metadata) ?? {};
634
- const plan = {
635
- stages: [],
636
- triggers: 0,
637
- ...readPlanVariables(doc),
638
- bindings,
639
- caseExitConditions: asArray(metadata.caseExitRules),
640
- caseSla: asArray(metadata.slaRules).length > 0,
641
- caseSlaRules: asArray(metadata.slaRules)
642
- };
643
- for (const node of asArray(doc.nodes)) {
644
- const record = asRecord(node);
645
- if (!record)
646
- continue;
647
- const typed = record;
648
- if (isAnyTriggerNode(typed)) {
649
- plan.triggers += 1;
650
- continue;
651
- }
652
- if (!isStageNode(typed))
653
- continue;
654
- const data = asRecord(record.data) ?? {};
655
- plan.stages.push({
656
- name: (typeof data.label === "string" ? data.label : undefined) ?? (typeof data.displayName === "string" ? data.displayName : undefined),
657
- tasks: readPlanTasks(data, bindings),
658
- entry: asArray(data.entryConditions),
659
- exit: asArray(data.exitConditions),
660
- sla: asArray(data.slaRules)
661
- });
662
- }
663
- return plan;
664
- };
665
- var resolveTasks = (sddTasks, planTasks) => {
666
- const bound = sddTasks.map(() => {
667
- return;
668
- });
669
- const taken = new Set;
670
- const free = (predicate) => planTasks.map((t, i) => ({ t, i })).filter(({ t, i }) => !taken.has(i) && predicate(t)).map(({ i }) => i);
671
- const bind = (row, index) => {
672
- bound[row] = index;
673
- taken.add(index);
674
- };
675
- sddTasks.forEach((task, row) => {
676
- const hits = free((t) => (t.name ?? "") === task.name);
677
- if (hits.length > 0)
678
- bind(row, hits[0]);
679
- });
680
- const ambiguous = new Set;
681
- sddTasks.forEach((task, row) => {
682
- if (bound[row] !== undefined)
683
- return;
684
- const key = norm(task.name);
685
- const hits = free((t) => norm(t.name) === key);
686
- if (hits.length === 1)
687
- bind(row, hits[0]);
688
- else if (hits.length > 1)
689
- ambiguous.add(row);
690
- });
691
- sddTasks.forEach((task, row) => {
692
- if (bound[row] !== undefined || ambiguous.has(row))
693
- return;
694
- const loose = normAnnotationless(task.name);
695
- const hits = free((t) => normAnnotationless(t.name) === loose);
696
- if (hits.length === 1)
697
- bind(row, hits[0]);
698
- });
699
- sddTasks.forEach((task, row) => {
700
- if (bound[row] !== undefined || ambiguous.has(row))
701
- return;
702
- const key = `${norm(task.name)} `;
703
- const hits = free((t) => norm(t.name).startsWith(key));
704
- if (hits.length === 1)
705
- bind(row, hits[0]);
706
- });
707
- return bound;
708
- };
709
- var ruleTotal = (conditions) => {
710
- let total = 0;
711
- for (const condition of conditions) {
712
- for (const group of asArray(asRecord(condition)?.rules)) {
713
- total += asArray(group).length;
714
- }
715
- }
716
- return total;
717
- };
718
- var error = (code, path, message) => ({ code, path, message, severity: "error" });
719
- var warning = (code, path, message) => ({ code, path, message, severity: "warning" });
720
- var coverageFinding = (path, label, kind, rows, conditions) => {
721
- if (!rows)
722
- return [];
723
- const total = ruleTotal(conditions);
724
- if (total >= rows)
725
- return [];
726
- return [
727
- error("STRICT_SDD_CONDITION_MISSING", path, total === 0 ? `${label}: the SDD declares ${rows} ${kind} condition row(s), the caseplan has no ${kind} rules.` : `${label}: the SDD declares ${rows} ${kind} condition row(s), the caseplan keeps ${total} ${kind} rule(s) — rows may group into fewer conditions, never into fewer rules.`)
728
- ];
729
- };
730
- var OPEN_QUOTES = new Set(['"', "“", "‘", "'"]);
731
- var CLOSE_QUOTES = new Set(['"', "”", "’", "'"]);
732
- var quotedArgs = (argumentList) => {
733
- const args = [];
734
- let at = 0;
735
- while (at < argumentList.length) {
736
- if (!OPEN_QUOTES.has(argumentList[at])) {
737
- at += 1;
738
- continue;
739
- }
740
- const from = at + 1;
741
- let end = from;
742
- while (end < argumentList.length && !CLOSE_QUOTES.has(argumentList[end])) {
743
- end += 1;
744
- }
745
- if (end >= argumentList.length)
746
- break;
747
- if (end > from)
748
- args.push(argumentList.slice(from, end));
749
- at = end + 1;
750
- }
751
- return args;
752
- };
753
- var findSlaCalls = (text) => {
754
- const calls = [];
755
- const name = "sla-status-change";
756
- text.split(`
757
- `).forEach((line, index) => {
758
- const lower = line.toLowerCase();
759
- let found = lower.indexOf(name);
760
- while (found !== -1) {
761
- const after = found + name.length;
762
- found = lower.indexOf(name, after);
763
- let open = after;
764
- while (open < line.length && (line[open] === " " || line[open] === "\t")) {
765
- open += 1;
766
- }
767
- if (!line.startsWith("(", open))
768
- continue;
769
- const close = line.indexOf(")", open);
770
- if (close === -1)
771
- continue;
772
- const args = quotedArgs(line.slice(open + 1, close));
773
- if (args.length > 0)
774
- calls.push({ line: index + 1, args });
775
- }
776
- });
777
- return calls;
778
- };
779
- var slaReferenceFindings = (text, source) => {
780
- const findings = [];
781
- for (const call of findSlaCalls(text)) {
782
- const at = `${source}:${call.line}`;
783
- if (call.args.length !== 2 && call.args.length !== 3) {
784
- findings.push(error("STRICT_SDD_SLA_REFERENCE_ARITY", at, `sla-status-change needs 2 quoted args (breach) or 3 (at-risk); got ${call.args.length}.`));
785
- }
786
- if (call.args[0].trim().toLowerCase() === "case") {
787
- findings.push(error("STRICT_SDD_SLA_REFERENCE_TARGET", at, 'sla-status-change target "Case" — the case-level target is the literal "root".'));
788
- }
789
- }
790
- return findings;
791
- };
792
- var bindingFindings = (plan, task, path, label) => {
793
- const findings = [];
794
- for (const attribute of ["name", "folderPath"]) {
795
- const id = bindingId(task.data[attribute]);
796
- if (id === undefined)
797
- continue;
798
- const binding = plan.bindings.find((b) => b.id === id);
799
- if (!binding)
800
- continue;
801
- const key = binding.resourceKey;
802
- if (typeof key === "string" && key !== "" && !key.split("/").at(-1)?.includes(".")) {
803
- findings.push(error("STRICT_SDD_BINDING_RESOURCE_KEY", path, `${label}: binding "${String(binding.id)}" has a bare resourceKey "${key}" — it needs the \`.<entry name>\` leaf suffix.`));
804
- }
805
- if (task.type === "api-workflow" && !binding.resourceSubType) {
806
- findings.push(error("STRICT_SDD_BINDING_RESOURCE_KEY", path, `${label}: api-workflow binding "${String(binding.id)}" is missing \`resourceSubType: "Api"\`.`));
807
- }
808
- }
809
- return findings;
810
- };
811
- var sameLiteral = (declared, actual) => {
812
- if (declared === actual)
813
- return true;
814
- const parse = (text) => {
815
- try {
816
- return JSON.parse(text);
817
- } catch {
818
- return;
819
- }
820
- };
821
- const canonical = (value) => {
822
- if (Array.isArray(value)) {
823
- return `[${value.map(canonical).join(",")}]`;
824
- }
825
- const record = asRecord(value);
826
- if (record) {
827
- return `{${Object.keys(record).sort((a2, b2) => a2.localeCompare(b2)).map((key) => `${JSON.stringify(key)}:${canonical(record[key])}`).join(",")}}`;
828
- }
829
- return JSON.stringify(value) ?? "null";
830
- };
831
- const a = parse(declared);
832
- const b = parse(actual);
833
- if (a === undefined || b === undefined) {
834
- return trimQuotes(declared) === trimQuotes(actual);
835
- }
836
- return canonical(a) === canonical(b);
837
- };
838
- var literalFindings = (task, found, path, label) => {
839
- const findings = [];
840
- const inputs = asArray(found.data.inputs).map(asRecord).filter((i) => i !== undefined);
841
- for (const declared of task.literalInputs) {
842
- const input = inputs.find((i) => norm(i.name) === norm(declared.name));
843
- if (!input)
844
- continue;
845
- const actual = input.value;
846
- if (typeof actual !== "string" || actual.startsWith("="))
847
- continue;
848
- if (sameLiteral(declared.value, actual))
849
- continue;
850
- const carried = actual === "" ? "an empty value" : `"${actual}"`;
851
- findings.push(warning("STRICT_SDD_LITERAL_MISMATCH", `${path}.data.inputs[${declared.name}]`, `${label}: input "${declared.name}" carries ${carried}, the SDD declares "${declared.value}". A literal that arrives truncated or rewritten runs with the wrong data.`));
852
- }
853
- return findings;
854
- };
855
- var extractFindings = (task, found, path, label) => {
856
- if (task.extractRows.length === 0)
857
- return [];
858
- const outputs = asArray(found.data.outputs).map(asRecord).filter((o) => o !== undefined);
859
- const findings = [];
860
- for (const declared of task.extractRows) {
861
- const wanted = `=${declared.field}`;
862
- const present = outputs.some((o) => o.source === wanted && o.var === declared.variable);
863
- if (present)
864
- continue;
865
- findings.push(error("STRICT_SDD_EXTRACT_MISSING", `${path}.data.outputs`, `${label}: no output writes "${declared.variable}". The SDD ` + `extracts \`${declared.field} -> ${declared.variable}\`, so ` + `the task needs an output with source "${wanted}" and var ` + `"${declared.variable}". Without it the variable is never ` + "written and anything reading it sees null."));
866
- }
867
- return findings;
868
- };
869
- var customOutputFindings = (task, found, path, label) => {
870
- if (task.customRows.length === 0)
871
- return [];
872
- const outputs = asArray(found.data.outputs).map(asRecord).filter((o) => o !== undefined);
873
- const findings = [];
874
- for (const declared of task.customRows) {
875
- const present = outputs.some((o) => o.custom === true && o.var === declared.variable);
876
- if (present)
877
- continue;
878
- findings.push(error("STRICT_SDD_CUSTOM_OUTPUT_MISSING", `${path}.data.outputs`, `${label}: nothing sets "${declared.variable}". The SDD assigns it \`${declared.expression}\`, so the task needs an output with \`custom: true\` and var "${declared.variable}". Without it no element in the packed BPMN writes the variable and it keeps its default.`));
879
- }
880
- return findings;
881
- };
882
- var gatedSlaFindings = (rules, path, label) => {
883
- if (rules.length === 0)
884
- return [];
885
- const expressions = rules.map((rule) => {
886
- const expression = asRecord(rule)?.expression;
887
- return typeof expression === "string" ? expression.trim() : "";
888
- });
889
- const isDefault = (expression) => expression === "" || norm(expression) === norm("=js:true");
890
- if (expressions.some(isDefault))
891
- return [];
892
- return [
893
- warning("STRICT_SDD_SLA_GATED_NEEDS_DEFAULT", path, `${label}: every SLA rule is gated by an expression and none is the \`=js:true\` default, so no SLA applies when no gate matches. Add a trailing unconditional rule if that is not intended.`)
894
- ];
895
- };
896
- var compareTask = (plan, task, found, stagePath, label) => {
897
- const issues = [];
898
- const taskPath = `${stagePath}.data.tasks[${found.name ?? task.name}]`;
899
- if (task.type && found.type && norm(task.type) !== norm(found.type)) {
900
- issues.push(error("STRICT_SDD_TASK_TYPE_MISMATCH", `${taskPath}.type`, `${label}: the SDD declares type "${task.type}", the caseplan has "${found.type}".`));
901
- }
902
- issues.push(...coverageFinding(`${taskPath}.entryConditions`, label, "entry", task.entryRows, found.entry));
903
- if (found.entry.length === 0) {
904
- issues.push(error("STRICT_SDD_ENTRY_RULE_EMPTY", `${taskPath}.entryConditions`, `${label}: no entryConditions in the caseplan. The default profile only warns, but a task with no entry rule hangs \`case debug\` indefinitely.`));
905
- } else if (ruleTotal(found.entry) === 0) {
906
- issues.push(error("STRICT_SDD_ENTRY_RULE_EMPTY", `${taskPath}.entryConditions`, `${label}: entryConditions carry no rules.`));
907
- }
908
- const isPlaceholder = Object.keys(found.data).length === 0;
909
- if (isPlaceholder && task.identityResolved) {
910
- const resolved = task.resolvedResource ? ` to "${task.resolvedResource}"` : "";
911
- issues.push(error("STRICT_SDD_PLACEHOLDER_RESOLVED", `${taskPath}.data`, `${label}: the caseplan has an empty \`data: {}\` (placeholder) but the SDD resolved the resource${resolved}.`));
912
- } else if (isPlaceholder) {
913
- issues.push(warning("STRICT_SDD_PLACEHOLDER_TASK", `${taskPath}.data`, `${label}: placeholder task (empty \`data\`) — the SDD leaves its resource unresolved.`));
914
- }
915
- issues.push(...bindingFindings(plan, found, taskPath, label), ...literalFindings(task, found, taskPath, label), ...extractFindings(task, found, taskPath, label), ...customOutputFindings(task, found, taskPath, label));
916
- return issues;
917
- };
918
- var variablePlacementFindings = (sdd, plan, name, key) => {
919
- const category = sdd.variableCategories.get(key);
920
- const required = VARIABLE_PLACEMENT.get(category ?? "");
921
- if (category === undefined || required === undefined)
922
- return [];
923
- const issues = [];
924
- for (const group of required) {
925
- if (plan.variableGroups[group].has(key))
926
- continue;
927
- const found = VARIABLE_GROUPS.filter((g) => plan.variableGroups[g].has(key));
928
- issues.push(error("STRICT_SDD_VARIABLE_GROUP_MISSING", `variables.${group}[${name}]`, `Variable "${name}": the SDD Category=${capitalize(category)} needs an entry in caseplan variables.${group}[], found only in ${found.join(", ")}. \`validate\` accepts half the pair and the argument then drops out of entry-points.json.`));
929
- }
930
- return issues;
931
- };
932
- var compareCaseLevel = (sdd, plan) => {
933
- const issues = [
934
- ...coverageFinding("metadata.caseExitRules", "case", "exit", sdd.caseExitRows, plan.caseExitConditions),
935
- ...gatedSlaFindings(plan.caseSlaRules, "metadata.slaRules", "case")
936
- ];
937
- if (sdd.caseSla && !plan.caseSla) {
938
- issues.push(error("STRICT_SDD_SLA_MISSING", "metadata.slaRules", "case: the SDD declares Case-Level SLA Escalation Rules, the caseplan metadata.slaRules is empty."));
939
- }
940
- if (sdd.triggers && plan.triggers < sdd.triggers) {
941
- issues.push(error("STRICT_SDD_TRIGGER_MISSING", "nodes", plan.triggers === 0 ? `case: the SDD declares ${sdd.triggers} trigger(s), the caseplan has no trigger node.` : `case: the SDD declares ${sdd.triggers} trigger(s), the caseplan has ${plan.triggers}.`));
942
- }
943
- const planVariables = new Set(plan.variables.map(norm));
944
- for (const name of sdd.variables) {
945
- const key = norm(name);
946
- if (!planVariables.has(key)) {
947
- issues.push(error("STRICT_SDD_VARIABLE_MISSING", `variables[${name}]`, `Variable "${name}" is declared in the SDD Case Variables table and absent from the caseplan.`));
948
- continue;
949
- }
950
- issues.push(...variablePlacementFindings(sdd, plan, name, key));
951
- }
952
- return issues;
953
- };
954
- var compareStage = (plan, stage, planStage) => {
955
- const stagePath = `nodes[${planStage.name ?? stage.name}]`;
956
- const stageLabel = `stage "${stage.name}"`;
957
- const issues = [
958
- ...coverageFinding(`${stagePath}.data.entryConditions`, stageLabel, "entry", stage.entryRows, planStage.entry),
959
- ...coverageFinding(`${stagePath}.data.exitConditions`, stageLabel, "exit", stage.exitRows, planStage.exit),
960
- ...gatedSlaFindings(planStage.sla, `${stagePath}.data.slaRules`, stageLabel)
961
- ];
962
- if (stage.hasSla && planStage.sla.length === 0) {
963
- issues.push(error("STRICT_SDD_SLA_MISSING", `${stagePath}.data.slaRules`, `${stageLabel}: the SDD declares a Stage SLA, the caseplan has no slaRules.`));
964
- }
965
- const bound = resolveTasks(stage.tasks, planStage.tasks);
966
- stage.tasks.forEach((task, row) => {
967
- const taskIndex = bound[row];
968
- const label = `${stageLabel} task "${task.name}"`;
969
- if (taskIndex === undefined) {
970
- issues.push(error("STRICT_SDD_TASK_MISSING", `${stagePath}.data.tasks[${task.name}]`, `${label} is declared in the SDD and absent from the caseplan.`));
971
- return;
972
- }
973
- issues.push(...compareTask(plan, task, planStage.tasks[taskIndex], stagePath, label));
974
- });
975
- planStage.tasks.forEach((extra, index) => {
976
- if (bound.includes(index))
977
- return;
978
- issues.push(warning("STRICT_SDD_TASK_EXTRA", `${stagePath}.data.tasks[${extra.name ?? index}]`, `${stageLabel} task "${extra.name ?? index}" is in the caseplan with no matching SDD task row.`));
979
- });
980
- return issues;
981
- };
982
- var compare = (sdd, plan) => {
983
- const issues = [];
984
- const stageBound = new Set;
985
- for (const stage of sdd.stages) {
986
- const key = norm(stage.name);
987
- let index = plan.stages.findIndex((candidate, at) => !stageBound.has(at) && norm(candidate.name) === key);
988
- if (index === -1) {
989
- const loose = normAnnotationless(stage.name);
990
- const hits = plan.stages.map((candidate, at) => ({ candidate, at })).filter(({ candidate, at }) => !stageBound.has(at) && normAnnotationless(candidate.name) === loose);
991
- if (hits.length === 1)
992
- index = hits[0].at;
993
- }
994
- if (index === -1) {
995
- issues.push(error("STRICT_SDD_STAGE_MISSING", `nodes[${stage.name}]`, `Stage "${stage.name}" is declared in the SDD and absent from the caseplan.`));
996
- continue;
997
- }
998
- stageBound.add(index);
999
- issues.push(...compareStage(plan, stage, plan.stages[index]));
1000
- }
1001
- plan.stages.forEach((extra, index) => {
1002
- if (stageBound.has(index))
1003
- return;
1004
- issues.push(warning("STRICT_SDD_STAGE_EXTRA", `nodes[${extra.name ?? index}]`, `Stage "${extra.name ?? index}" is in the caseplan with no matching SDD stage.`));
1005
- });
1006
- issues.push(...compareCaseLevel(sdd, plan));
1007
- return issues;
1008
- };
1009
- var auditCaseplanAgainstSdd = (parsed, sddText, sddName) => {
1010
- const sdd = parseSdd(sddText);
1011
- const issues = sdd.parseNotes.map((note) => warning("STRICT_SDD_PARSE_NOTE", sddName, note));
1012
- if (sdd.stages.length === 0) {
1013
- issues.push(error("STRICT_SDD_PARSE_EMPTY", sddName, `No stages parsed from "${sddName}", so every completeness check would pass without checking anything. Stage headings must read \`### Stage <n>: <name>\`.`));
1014
- return issues;
1015
- }
1016
- issues.push(...compare(sdd, parseCaseplan(parsed)));
1017
- issues.push(...slaReferenceFindings(sddText, sddName));
1018
- return issues;
1019
- };
1020
- export {
1021
- auditCaseplanAgainstSdd
1022
- };
1023
-
1024
- //# debugId=8E454AD3E138C86064756E2164756E21