@actuarial-ts/core 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +65 -226
  2. package/dist/capping.d.ts.map +1 -1
  3. package/dist/capping.js +39 -6
  4. package/dist/capping.js.map +1 -1
  5. package/dist/casualtyDiagnostics.d.ts +19 -49
  6. package/dist/casualtyDiagnostics.d.ts.map +1 -1
  7. package/dist/casualtyDiagnostics.js +84 -116
  8. package/dist/casualtyDiagnostics.js.map +1 -1
  9. package/dist/diagnosticAggregation.d.ts +32 -0
  10. package/dist/diagnosticAggregation.d.ts.map +1 -0
  11. package/dist/diagnosticAggregation.js +73 -0
  12. package/dist/diagnosticAggregation.js.map +1 -0
  13. package/dist/diagnosticDefinitions.d.ts +289 -0
  14. package/dist/diagnosticDefinitions.d.ts.map +1 -0
  15. package/dist/diagnosticDefinitions.js +1688 -0
  16. package/dist/diagnosticDefinitions.js.map +1 -0
  17. package/dist/diagnosticDerivations.d.ts +35 -0
  18. package/dist/diagnosticDerivations.d.ts.map +1 -0
  19. package/dist/diagnosticDerivations.js +224 -0
  20. package/dist/diagnosticDerivations.js.map +1 -0
  21. package/dist/diagnosticExposure.d.ts +51 -0
  22. package/dist/diagnosticExposure.d.ts.map +1 -0
  23. package/dist/diagnosticExposure.js +273 -0
  24. package/dist/diagnosticExposure.js.map +1 -0
  25. package/dist/diagnosticExpressions.d.ts +56 -0
  26. package/dist/diagnosticExpressions.d.ts.map +1 -0
  27. package/dist/diagnosticExpressions.js +124 -0
  28. package/dist/diagnosticExpressions.js.map +1 -0
  29. package/dist/diagnosticFormulas.d.ts +198 -0
  30. package/dist/diagnosticFormulas.d.ts.map +1 -0
  31. package/dist/diagnosticFormulas.js +219 -0
  32. package/dist/diagnosticFormulas.js.map +1 -0
  33. package/dist/diagnosticIdentity.d.ts +251 -0
  34. package/dist/diagnosticIdentity.d.ts.map +1 -0
  35. package/dist/diagnosticIdentity.js +721 -0
  36. package/dist/diagnosticIdentity.js.map +1 -0
  37. package/dist/diagnosticOrdering.d.ts +8 -0
  38. package/dist/diagnosticOrdering.d.ts.map +1 -0
  39. package/dist/diagnosticOrdering.js +73 -0
  40. package/dist/diagnosticOrdering.js.map +1 -0
  41. package/dist/diagnosticPeriodAxis.d.ts +9 -0
  42. package/dist/diagnosticPeriodAxis.d.ts.map +1 -0
  43. package/dist/diagnosticPeriodAxis.js +69 -0
  44. package/dist/diagnosticPeriodAxis.js.map +1 -0
  45. package/dist/diagnosticPeriods.d.ts +15 -0
  46. package/dist/diagnosticPeriods.d.ts.map +1 -0
  47. package/dist/diagnosticPeriods.js +50 -0
  48. package/dist/diagnosticPeriods.js.map +1 -0
  49. package/dist/diagnosticPreparation.d.ts +131 -0
  50. package/dist/diagnosticPreparation.d.ts.map +1 -0
  51. package/dist/diagnosticPreparation.js +1539 -0
  52. package/dist/diagnosticPreparation.js.map +1 -0
  53. package/dist/diagnosticReview.d.ts +66 -0
  54. package/dist/diagnosticReview.d.ts.map +1 -0
  55. package/dist/diagnosticReview.js +490 -0
  56. package/dist/diagnosticReview.js.map +1 -0
  57. package/dist/diagnosticRules.d.ts +32 -0
  58. package/dist/diagnosticRules.d.ts.map +1 -0
  59. package/dist/diagnosticRules.js +32 -0
  60. package/dist/diagnosticRules.js.map +1 -0
  61. package/dist/diagnosticRunner.d.ts +86 -0
  62. package/dist/diagnosticRunner.d.ts.map +1 -0
  63. package/dist/diagnosticRunner.js +703 -0
  64. package/dist/diagnosticRunner.js.map +1 -0
  65. package/dist/diagnosticRuntime.d.ts +26 -0
  66. package/dist/diagnosticRuntime.d.ts.map +1 -0
  67. package/dist/diagnosticRuntime.js +243 -0
  68. package/dist/diagnosticRuntime.js.map +1 -0
  69. package/dist/diagnosticSourceOrdering.d.ts +6 -0
  70. package/dist/diagnosticSourceOrdering.d.ts.map +1 -0
  71. package/dist/diagnosticSourceOrdering.js +38 -0
  72. package/dist/diagnosticSourceOrdering.js.map +1 -0
  73. package/dist/index.d.ts +28 -1
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +16 -1
  76. package/dist/index.js.map +1 -1
  77. package/dist/mack.d.ts +4 -0
  78. package/dist/mack.d.ts.map +1 -1
  79. package/dist/mack.js +32 -4
  80. package/dist/mack.js.map +1 -1
  81. package/dist/triangle.d.ts.map +1 -1
  82. package/dist/triangle.js +59 -9
  83. package/dist/triangle.js.map +1 -1
  84. package/dist/types.d.ts +21 -0
  85. package/dist/types.d.ts.map +1 -1
  86. package/dist/types.js +128 -0
  87. package/dist/types.js.map +1 -1
  88. package/dist/version.d.ts +3 -0
  89. package/dist/version.d.ts.map +1 -0
  90. package/dist/version.js +3 -0
  91. package/dist/version.js.map +1 -0
  92. package/package.json +4 -3
  93. package/src/capping.ts +109 -18
  94. package/src/casualtyDiagnostics.ts +79 -189
  95. package/src/diagnosticAggregation.ts +128 -0
  96. package/src/diagnosticDefinitions.ts +3624 -0
  97. package/src/diagnosticDerivations.ts +321 -0
  98. package/src/diagnosticExposure.ts +482 -0
  99. package/src/diagnosticExpressions.ts +255 -0
  100. package/src/diagnosticFormulas.ts +350 -0
  101. package/src/diagnosticIdentity.ts +1267 -0
  102. package/src/diagnosticOrdering.ts +106 -0
  103. package/src/diagnosticPeriodAxis.ts +92 -0
  104. package/src/diagnosticPeriods.ts +102 -0
  105. package/src/diagnosticPreparation.ts +2475 -0
  106. package/src/diagnosticReview.ts +897 -0
  107. package/src/diagnosticRules.ts +69 -0
  108. package/src/diagnosticRunner.ts +1114 -0
  109. package/src/diagnosticRuntime.ts +264 -0
  110. package/src/diagnosticSourceOrdering.ts +50 -0
  111. package/src/index.ts +184 -1
  112. package/src/mack.ts +72 -9
  113. package/src/triangle.ts +103 -13
  114. package/src/types.ts +196 -0
  115. package/src/version.ts +2 -0
  116. package/dist/metricDiagnostics.d.ts +0 -212
  117. package/dist/metricDiagnostics.d.ts.map +0 -1
  118. package/dist/metricDiagnostics.js +0 -627
  119. package/dist/metricDiagnostics.js.map +0 -1
  120. package/src/metricDiagnostics.ts +0 -876
package/src/triangle.ts CHANGED
@@ -5,6 +5,7 @@ import type {
5
5
  TriangleKind,
6
6
  } from "./types.js";
7
7
  import { ReservingError } from "./types.js";
8
+ import { isDiagnosticToken, isRealIsoDate } from "./diagnosticRuntime.js";
8
9
 
9
10
  /**
10
11
  * Builds development triangles from claim-level evaluation snapshots.
@@ -27,16 +28,12 @@ interface ParsedDate {
27
28
  }
28
29
 
29
30
  function parseISO(date: string): ParsedDate {
30
- const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(date);
31
- if (!match) {
31
+ if (!isRealIsoDate(date))
32
32
  throw new ReservingError("BAD_DATE", `Invalid ISO date: "${date}"`);
33
- }
33
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date)!;
34
34
  const y = Number(match[1]);
35
35
  const m = Number(match[2]);
36
36
  const d = Number(match[3]);
37
- if (m < 1 || m > 12 || d < 1 || d > 31) {
38
- throw new ReservingError("BAD_DATE", `Invalid ISO date: "${date}"`);
39
- }
40
37
  return { y, m, d };
41
38
  }
42
39
 
@@ -90,6 +87,7 @@ export interface TriangleSet {
90
87
 
91
88
  interface ClaimTimeline {
92
89
  originIdx: number;
90
+ accidentISO: string;
93
91
  reportISO: string;
94
92
  /** Snapshots sorted ascending by evaluation date. */
95
93
  snapshots: ClaimSnapshot[];
@@ -101,9 +99,17 @@ export function buildTriangles(
101
99
  ): TriangleSet {
102
100
  const { cadence, asOfDate } = options;
103
101
  if (claims.length === 0) {
104
- throw new ReservingError("NO_CLAIMS", "Cannot build triangles from an empty loss run");
102
+ throw new ReservingError(
103
+ "NO_CLAIMS",
104
+ "Cannot build triangles from an empty loss run",
105
+ );
105
106
  }
106
107
  const asOf = parseISO(asOfDate);
108
+ if (cadence !== "annual" && cadence !== "quarterly")
109
+ throw new ReservingError(
110
+ "BAD_ORIGIN",
111
+ "Cadence must be annual or quarterly",
112
+ );
107
113
  const asOfMonth = monthIndex(asOf);
108
114
  const asOfIsMonthEnd = asOf.d === daysInMonth(asOf.y, asOf.m);
109
115
  // The latest complete evaluation month.
@@ -115,15 +121,53 @@ export function buildTriangles(
115
121
  let minPeriod = Infinity;
116
122
  let maxPeriod = -Infinity;
117
123
  for (const snap of claims) {
124
+ if (!isDiagnosticToken(snap.claimId))
125
+ throw new ReservingError(
126
+ "BAD_ORIGIN",
127
+ "Claim id must be a nonempty token",
128
+ );
118
129
  const accident = parseISO(snap.accidentDate);
130
+ parseISO(snap.reportDate);
131
+ parseISO(snap.evaluationDate);
132
+ if (
133
+ snap.reportDate < snap.accidentDate ||
134
+ snap.evaluationDate < snap.reportDate
135
+ )
136
+ throw new ReservingError(
137
+ "BAD_DATE",
138
+ `Claim ${snap.claimId} dates must satisfy accident <= report <= evaluation`,
139
+ );
140
+ if (!Number.isFinite(snap.paidToDate) || !Number.isFinite(snap.caseReserve))
141
+ throw new ReservingError(
142
+ "BAD_LOSSES",
143
+ `Claim ${snap.claimId} contains a non-finite amount`,
144
+ );
145
+ if (snap.status !== "open" && snap.status !== "closed")
146
+ throw new ReservingError(
147
+ "BAD_LOSSES",
148
+ `Claim ${snap.claimId} has an invalid status`,
149
+ );
119
150
  if (snap.evaluationDate > asOfDate) continue; // beyond the analysis date
120
151
  const period = periodIndexOf(accident, cadence);
121
152
  minPeriod = Math.min(minPeriod, period);
122
153
  maxPeriod = Math.max(maxPeriod, period);
123
154
  let timeline = byClaim.get(snap.claimId);
124
155
  if (!timeline) {
125
- timeline = { originIdx: period, reportISO: snap.reportDate, snapshots: [] };
156
+ timeline = {
157
+ originIdx: period,
158
+ accidentISO: snap.accidentDate,
159
+ reportISO: snap.reportDate,
160
+ snapshots: [],
161
+ };
126
162
  byClaim.set(snap.claimId, timeline);
163
+ } else if (
164
+ timeline.accidentISO !== snap.accidentDate ||
165
+ timeline.reportISO !== snap.reportDate
166
+ ) {
167
+ throw new ReservingError(
168
+ "BAD_ORIGIN",
169
+ `Claim ${snap.claimId} has conflicting accident or report dates across snapshots`,
170
+ );
127
171
  }
128
172
  timeline.snapshots.push(snap);
129
173
  }
@@ -135,13 +179,18 @@ export function buildTriangles(
135
179
  }
136
180
  for (const timeline of byClaim.values()) {
137
181
  timeline.snapshots.sort((a, b) =>
138
- a.evaluationDate < b.evaluationDate ? -1 : a.evaluationDate > b.evaluationDate ? 1 : 0,
182
+ a.evaluationDate < b.evaluationDate
183
+ ? -1
184
+ : a.evaluationDate > b.evaluationDate
185
+ ? 1
186
+ : 0,
139
187
  );
140
188
  }
141
189
 
142
190
  const nOrigins = maxPeriod - minPeriod + 1;
143
191
  const origins: string[] = [];
144
- for (let p = minPeriod; p <= maxPeriod; p++) origins.push(periodLabel(p, cadence));
192
+ for (let p = minPeriod; p <= maxPeriod; p++)
193
+ origins.push(periodLabel(p, cadence));
145
194
 
146
195
  // Ages available to the oldest origin period determine the column count.
147
196
  const oldestStart = periodStartMonth(minPeriod, cadence);
@@ -198,7 +247,8 @@ export function buildTriangles(
198
247
  else break;
199
248
  }
200
249
  const paid = state?.paidToDate ?? 0;
201
- const caseReserve = state?.status === "open" ? (state?.caseReserve ?? 0) : 0;
250
+ const caseReserve =
251
+ state?.status === "open" ? (state?.caseReserve ?? 0) : 0;
202
252
  const isClosed = state?.status === "closed";
203
253
  add(set.reportedCount, i, j, 1);
204
254
  add(set.paid, i, j, paid);
@@ -223,13 +273,53 @@ export function triangleFromGrid(
223
273
  ages: number[],
224
274
  values: (number | null)[][],
225
275
  ): Triangle {
276
+ const kinds: readonly TriangleKind[] = [
277
+ "paid",
278
+ "incurred",
279
+ "caseReserve",
280
+ "reportedCount",
281
+ "openCount",
282
+ "closedCount",
283
+ "closedWithPayCount",
284
+ ];
285
+ if (!kinds.includes(kind))
286
+ throw new ReservingError("SHAPE", "Unknown triangle kind");
287
+ if (
288
+ origins.some((origin) => !isDiagnosticToken(origin)) ||
289
+ new Set(origins).size !== origins.length
290
+ ) {
291
+ throw new ReservingError("SHAPE", "Origins must be unique nonempty tokens");
292
+ }
293
+ if (
294
+ ages.some((age) => !Number.isSafeInteger(age) || age <= 0) ||
295
+ ages.some((age, index) => index > 0 && age <= ages[index - 1]!)
296
+ ) {
297
+ throw new ReservingError(
298
+ "SHAPE",
299
+ "Development ages must be finite positive safe integers in strictly ascending order",
300
+ );
301
+ }
226
302
  if (values.length !== origins.length) {
227
303
  throw new ReservingError("SHAPE", "Row count does not match origin count");
228
304
  }
229
305
  for (const row of values) {
230
306
  if (row.length !== ages.length) {
231
- throw new ReservingError("SHAPE", "Column count does not match age count");
307
+ throw new ReservingError(
308
+ "SHAPE",
309
+ "Column count does not match age count",
310
+ );
311
+ }
312
+ if (row.some((value) => value !== null && !Number.isFinite(value))) {
313
+ throw new ReservingError(
314
+ "SHAPE",
315
+ "Observed triangle cells must be finite numbers",
316
+ );
232
317
  }
233
318
  }
234
- return { kind, origins: [...origins], ages: [...ages], values: values.map((r) => [...r]) };
319
+ return {
320
+ kind,
321
+ origins: [...origins],
322
+ ages: [...ages],
323
+ values: values.map((r) => [...r]),
324
+ };
235
325
  }
package/src/types.ts CHANGED
@@ -190,6 +190,10 @@ export interface MackResult {
190
190
  tailFactor?: number;
191
191
  /** Extrapolated sigma^2 for the tail step; present only when a tail was applied. */
192
192
  sigmaSquaredTail?: number;
193
+ /** Explicit tail-factor estimation error when supplied under Mack (1999). */
194
+ tailStandardError?: number;
195
+ /** Explicit tail random-error scale when supplied under Mack (1999). */
196
+ tailSigma?: number;
193
197
  rows: MackRow[];
194
198
  totals: {
195
199
  latest: number;
@@ -295,6 +299,198 @@ export interface DiagnosticFinding {
295
299
  message: string;
296
300
  }
297
301
 
302
+ export type DiagnosticValidationErrorCode =
303
+ | "INVALID_DIAGNOSTIC_DEFINITION"
304
+ | "INVALID_DIAGNOSTIC_INPUT"
305
+ | "INVALID_DIAGNOSTIC_CONFIGURATION"
306
+ | "INVALID_DIAGNOSTIC_VIEW";
307
+
308
+ export type DiagnosticValidationIssueCode =
309
+ | "missing-required"
310
+ | "invalid-type"
311
+ | "unknown-key"
312
+ | "invalid-string"
313
+ | "invalid-number"
314
+ | "invalid-json-value"
315
+ | "duplicate-id"
316
+ | "unknown-reference"
317
+ | "incompatible-semantics"
318
+ | "invalid-period"
319
+ | "invalid-input-relationship"
320
+ | "invalid-configuration"
321
+ | "expression-limit"
322
+ | "cycle";
323
+
324
+ export type DiagnosticValidationDomain =
325
+ | "definition"
326
+ | "input"
327
+ | "configuration"
328
+ | "view";
329
+
330
+ export interface DiagnosticValidationIssue {
331
+ readonly domain: DiagnosticValidationDomain;
332
+ readonly code: DiagnosticValidationIssueCode;
333
+ /** Canonical singular JSONPath, rooted at `$`. */
334
+ readonly path: string;
335
+ readonly message: string;
336
+ }
337
+
338
+ const DIAGNOSTIC_DOMAIN_ORDER: readonly DiagnosticValidationDomain[] = [
339
+ "definition",
340
+ "input",
341
+ "configuration",
342
+ "view",
343
+ ];
344
+
345
+ const DIAGNOSTIC_ISSUE_ORDER: readonly DiagnosticValidationIssueCode[] = [
346
+ "missing-required",
347
+ "invalid-type",
348
+ "unknown-key",
349
+ "invalid-string",
350
+ "invalid-number",
351
+ "invalid-json-value",
352
+ "duplicate-id",
353
+ "unknown-reference",
354
+ "incompatible-semantics",
355
+ "invalid-period",
356
+ "invalid-input-relationship",
357
+ "invalid-configuration",
358
+ "expression-limit",
359
+ "cycle",
360
+ ];
361
+
362
+ function compareCodeUnits(left: string, right: string): number {
363
+ return left === right ? 0 : left < right ? -1 : 1;
364
+ }
365
+
366
+ type DiagnosticPathSegment =
367
+ | { readonly kind: "property"; readonly value: string }
368
+ | { readonly kind: "index"; readonly value: number };
369
+
370
+ function diagnosticPathSegments(
371
+ path: string,
372
+ ): readonly DiagnosticPathSegment[] {
373
+ const segments: DiagnosticPathSegment[] = [];
374
+ let cursor = 1;
375
+ while (cursor < path.length) {
376
+ if (path[cursor] === ".") {
377
+ const start = ++cursor;
378
+ while (
379
+ cursor < path.length &&
380
+ path[cursor] !== "." &&
381
+ path[cursor] !== "["
382
+ )
383
+ cursor++;
384
+ segments.push({ kind: "property", value: path.slice(start, cursor) });
385
+ continue;
386
+ }
387
+ if (path[cursor] === "[") {
388
+ const close = path.indexOf("]", cursor);
389
+ if (close < 0) return [{ kind: "property", value: path }];
390
+ const token = path.slice(cursor + 1, close);
391
+ if (/^\d+$/.test(token))
392
+ segments.push({ kind: "index", value: Number(token) });
393
+ else {
394
+ try {
395
+ segments.push({
396
+ kind: "property",
397
+ value: JSON.parse(token) as string,
398
+ });
399
+ } catch {
400
+ return [{ kind: "property", value: path }];
401
+ }
402
+ }
403
+ cursor = close + 1;
404
+ continue;
405
+ }
406
+ return [{ kind: "property", value: path }];
407
+ }
408
+ return segments;
409
+ }
410
+
411
+ function compareDiagnosticPaths(left: string, right: string): number {
412
+ if (left === right) return 0;
413
+ const a = diagnosticPathSegments(left);
414
+ const b = diagnosticPathSegments(right);
415
+ const length = Math.min(a.length, b.length);
416
+ for (let index = 0; index < length; index++) {
417
+ const x = a[index]!;
418
+ const y = b[index]!;
419
+ if (x.kind !== y.kind) return x.kind === "property" ? -1 : 1;
420
+ const compared =
421
+ x.kind === "index"
422
+ ? x.value -
423
+ (y as Extract<DiagnosticPathSegment, { kind: "index" }>).value
424
+ : compareCodeUnits(
425
+ x.value,
426
+ (y as Extract<DiagnosticPathSegment, { kind: "property" }>).value,
427
+ );
428
+ if (compared !== 0) return compared;
429
+ }
430
+ return a.length - b.length;
431
+ }
432
+
433
+ function normalizeDiagnosticIssues(
434
+ issues: readonly DiagnosticValidationIssue[],
435
+ ): readonly DiagnosticValidationIssue[] {
436
+ if (issues.length === 0) {
437
+ throw new Error("DiagnosticValidationError requires at least one issue");
438
+ }
439
+ const unique = new Map<
440
+ string,
441
+ Map<string, Map<string, Map<string, DiagnosticValidationIssue>>>
442
+ >();
443
+ for (const issue of issues) {
444
+ const normalized = Object.freeze({ ...issue });
445
+ const byCode = unique.get(issue.domain) ?? new Map();
446
+ unique.set(issue.domain, byCode);
447
+ const byPath = byCode.get(issue.code) ?? new Map();
448
+ byCode.set(issue.code, byPath);
449
+ const byMessage = byPath.get(issue.path) ?? new Map();
450
+ byPath.set(issue.path, byMessage);
451
+ if (!byMessage.has(issue.message)) byMessage.set(issue.message, normalized);
452
+ }
453
+ const flattened = [...unique.values()].flatMap((byCode) =>
454
+ [...byCode.values()].flatMap((byPath) =>
455
+ [...byPath.values()].flatMap((byMessage) => [...byMessage.values()]),
456
+ ),
457
+ );
458
+ return Object.freeze(
459
+ flattened.sort(
460
+ (left, right) =>
461
+ DIAGNOSTIC_DOMAIN_ORDER.indexOf(left.domain) -
462
+ DIAGNOSTIC_DOMAIN_ORDER.indexOf(right.domain) ||
463
+ DIAGNOSTIC_ISSUE_ORDER.indexOf(left.code) -
464
+ DIAGNOSTIC_ISSUE_ORDER.indexOf(right.code) ||
465
+ compareDiagnosticPaths(left.path, right.path) ||
466
+ compareCodeUnits(left.code, right.code) ||
467
+ compareCodeUnits(left.message, right.message),
468
+ ),
469
+ );
470
+ }
471
+
472
+ /** Public, deterministic validation failure for every generalized diagnostic boundary. */
473
+ export class DiagnosticValidationError extends Error {
474
+ readonly code: DiagnosticValidationErrorCode;
475
+ readonly path: string;
476
+ readonly issues: readonly DiagnosticValidationIssue[];
477
+
478
+ constructor(issues: readonly DiagnosticValidationIssue[]) {
479
+ const normalized = normalizeDiagnosticIssues(issues);
480
+ super(normalized[0]!.message);
481
+ this.name = "DiagnosticValidationError";
482
+ this.issues = normalized;
483
+ this.path = normalized[0]!.path;
484
+ this.code = {
485
+ definition: "INVALID_DIAGNOSTIC_DEFINITION",
486
+ input: "INVALID_DIAGNOSTIC_INPUT",
487
+ configuration: "INVALID_DIAGNOSTIC_CONFIGURATION",
488
+ view: "INVALID_DIAGNOSTIC_VIEW",
489
+ }[normalized[0]!.domain] as DiagnosticValidationErrorCode;
490
+ Object.freeze(this);
491
+ }
492
+ }
493
+
298
494
  /**
299
495
  * Every machine-readable code a ReservingError can carry. This registry is
300
496
  * public contract: consumers may switch exhaustively on ReservingErrorCode,
package/src/version.ts ADDED
@@ -0,0 +1,2 @@
1
+ /** This package's runtime version. A test pins it to package.json. */
2
+ export const CORE_PACKAGE_VERSION = "0.6.1";
@@ -1,212 +0,0 @@
1
- import { type DiagnosticFinding } from "./types.js";
2
- export type SparseValuePolicy = "preserve-null" | "zero-fill";
3
- export type DiagnosticMeasureMap = Readonly<Record<string, number | null | undefined>>;
4
- export type MeasureExpression = {
5
- op: "measure";
6
- measure: string;
7
- } | {
8
- op: "add";
9
- terms: readonly MeasureExpression[];
10
- } | {
11
- op: "subtract";
12
- left: MeasureExpression;
13
- right: MeasureExpression;
14
- };
15
- export interface DiagnosticWarning {
16
- code: "MISSING_COMPONENT" | "NON_FINITE_COMPONENT" | "NON_FINITE_NUMERATOR" | "NON_FINITE_RESULT" | "INVALID_DENOMINATOR" | "INCOMPLETE_EXPOSURE" | "CONFLICTING_EXPOSURE" | "DUPLICATE_EXPOSURE_KEY" | "PAID_EXCEEDS_INCURRED" | (string & {});
17
- message: string;
18
- component?: string;
19
- exposureKey?: string;
20
- }
21
- /** Adapts structured metric warnings to the existing core diagnostic finding vocabulary. */
22
- export declare function diagnosticWarningToFinding(warning: DiagnosticWarning): DiagnosticFinding;
23
- export interface MetricWarningRule {
24
- code: "PAID_EXCEEDS_INCURRED";
25
- when: "numerator-greater-than-denominator";
26
- message: string;
27
- tolerance?: number;
28
- }
29
- export interface MetricDefinition {
30
- id: string;
31
- version: string;
32
- displayName: string;
33
- description: string;
34
- unit: "count-per-million" | "ratio" | "currency-per-exposure" | "currency-per-claim" | (string & {});
35
- scale: number;
36
- numerator: MeasureExpression;
37
- denominator: MeasureExpression;
38
- numeratorLabel: string;
39
- denominatorLabel: string;
40
- basis: string;
41
- requiredComponents: readonly string[];
42
- warningRules?: readonly MetricWarningRule[];
43
- /** Optional pure caller rule for domain warnings beyond the built-in comparisons. */
44
- evaluateWarnings?: (context: MetricWarningContext) => readonly DiagnosticWarning[];
45
- }
46
- export interface MetricWarningContext {
47
- definition: MetricDefinition;
48
- components: Readonly<Record<string, number | null>>;
49
- rawNumerator: number | null;
50
- rawDenominator: number | null;
51
- value: number | null;
52
- }
53
- export interface MetricEvaluation {
54
- metricId: string;
55
- metricVersion: string;
56
- value: number | null;
57
- rawNumerator: number | null;
58
- rawDenominator: number | null;
59
- numeratorLabel: string;
60
- denominatorLabel: string;
61
- unit: MetricDefinition["unit"];
62
- scale: number;
63
- basis: string;
64
- rawComponents: Record<string, number | null>;
65
- warnings: DiagnosticWarning[];
66
- }
67
- export interface MeasureAggregateCell {
68
- sum: number;
69
- observed: number;
70
- missing: number;
71
- nonFinite: number;
72
- }
73
- /** Mergeable sufficient statistics: grouping in stages gives the same result. */
74
- export interface MeasureAggregate {
75
- components: Record<string, MeasureAggregateCell>;
76
- }
77
- export declare function aggregateMeasures(rows: readonly DiagnosticMeasureMap[]): MeasureAggregate;
78
- export declare function mergeMeasureAggregates(aggregates: readonly MeasureAggregate[]): MeasureAggregate;
79
- export interface FinalizedMeasures {
80
- measures: Record<string, number | null>;
81
- warnings: DiagnosticWarning[];
82
- }
83
- export declare function finalizeMeasureAggregate(aggregate: MeasureAggregate, sparsePolicy?: SparseValuePolicy): FinalizedMeasures;
84
- export declare function measureExpressionComponents(expression: MeasureExpression): string[];
85
- export declare function evaluateMetric(definition: MetricDefinition, components: DiagnosticMeasureMap, inheritedWarnings?: readonly DiagnosticWarning[]): MetricEvaluation;
86
- export type LayerExpression = {
87
- op: "measure";
88
- measure: string;
89
- } | {
90
- op: "add";
91
- terms: readonly LayerExpression[];
92
- } | {
93
- op: "claim-cap";
94
- measure: string;
95
- limit: number;
96
- };
97
- export interface AmountLayerDefinition {
98
- id: string;
99
- displayName: string;
100
- paidMeasure: string;
101
- incurredMeasure: string;
102
- paid: LayerExpression;
103
- incurred: LayerExpression;
104
- /** Documents whether inputs are already limited or this layer caps claim rows. */
105
- basis: "pre-capped-additive" | "claim-level-cap" | "unlimited-additive";
106
- }
107
- export interface DiagnosticClaimRow<T = unknown> {
108
- dimensions: T;
109
- measures: DiagnosticMeasureMap;
110
- }
111
- /** Applies claim caps before aggregation; this function intentionally accepts claim rows, not aggregates. */
112
- export declare function deriveAmountLayers<T>(rows: readonly DiagnosticClaimRow<T>[], layers: readonly AmountLayerDefinition[]): DiagnosticClaimRow<T>[];
113
- export interface DiagnosticLossRow<TDimensions = unknown> {
114
- id: string;
115
- group: string;
116
- origin: string;
117
- valuation: string;
118
- ageMonths: number;
119
- /** Optional caller-mapped policy/fiscal period (for example a Q3-Q2 year). */
120
- policyPeriod?: string;
121
- /** Optional caller-owned grouping metadata; `group` remains the stable key. */
122
- dimensions?: TDimensions;
123
- measures: DiagnosticMeasureMap;
124
- }
125
- export interface DiagnosticExposureRow<TDimensions = unknown> {
126
- /** Stable exposure identity. Repeated snapshots with the same key count once. */
127
- key: string;
128
- group: string;
129
- origin: string;
130
- valuation?: string;
131
- measures: DiagnosticMeasureMap;
132
- complete?: boolean;
133
- dimensions?: TDimensions;
134
- }
135
- export interface DiagnosticsFilter {
136
- groups?: readonly string[];
137
- origins?: readonly string[];
138
- originFrom?: string;
139
- originThrough?: string;
140
- valuations?: readonly string[];
141
- valuationFrom?: string;
142
- valuationThrough?: string;
143
- policyPeriods?: readonly string[];
144
- minAgeMonths?: number;
145
- maxAgeMonths?: number;
146
- }
147
- export interface DiagnosticEmergencePoint<TDimensions = unknown> {
148
- group: string;
149
- dimensions?: TDimensions;
150
- origin: string;
151
- valuation: string;
152
- ageMonths: number;
153
- components: Record<string, number | null>;
154
- componentWarnings: DiagnosticWarning[];
155
- metrics: Record<string, MetricEvaluation>;
156
- }
157
- export interface DiagnosticMetricTriangle {
158
- group: string;
159
- metricId: string;
160
- origins: string[];
161
- ages: number[];
162
- values: (number | null)[][];
163
- cells: (MetricEvaluation | null)[][];
164
- }
165
- export interface MetricDiagnosticsResult<TDimensions = unknown> {
166
- emergence: DiagnosticEmergencePoint<TDimensions>[];
167
- triangles: DiagnosticMetricTriangle[];
168
- latestDiagonal: DiagnosticEmergencePoint<TDimensions>[];
169
- }
170
- export interface RunMetricDiagnosticsInput<TDimensions = unknown> {
171
- losses: readonly DiagnosticLossRow<TDimensions>[];
172
- exposures?: readonly DiagnosticExposureRow<TDimensions>[];
173
- metrics: readonly MetricDefinition[];
174
- sparsePolicy?: SparseValuePolicy;
175
- filter?: DiagnosticsFilter;
176
- /** Maps source group keys to requested aggregate keys before summation. */
177
- groupMap?: Readonly<Record<string, string>>;
178
- /** Metadata for mapped/combined output groups. */
179
- groupDimensions?: Readonly<Record<string, TDimensions>>;
180
- }
181
- export interface DiagnosticExposureReconciliationFinding {
182
- code: "DUPLICATE_EXPOSURE_KEY" | "CONFLICTING_EXPOSURE";
183
- exposureKey: string;
184
- group: string;
185
- origin: string;
186
- message: string;
187
- }
188
- export interface ReconciledDiagnosticExposures<TDimensions = unknown> {
189
- exposures: DiagnosticExposureRow<TDimensions>[];
190
- findings: DiagnosticExposureReconciliationFinding[];
191
- }
192
- /**
193
- * Reconciles stable exposure keys before aggregation. Identical valuation
194
- * copies collapse to one row. Conflicting copies become one incomplete/null
195
- * row so exposure-based metrics fail closed rather than using a partial base.
196
- */
197
- export declare function reconcileDiagnosticExposureKeys<TDimensions = unknown>(rows: readonly DiagnosticExposureRow<TDimensions>[]): ReconciledDiagnosticExposures<TDimensions>;
198
- /**
199
- * Generic quarterly diagnostics engine. Loss rows aggregate by
200
- * group/origin/valuation; exposure rows aggregate once by stable exposure key;
201
- * every metric then divides the aggregated expressions exactly once.
202
- */
203
- export declare function runMetricDiagnostics<TDimensions = unknown>(input: RunMetricDiagnosticsInput<TDimensions>): MetricDiagnosticsResult<TDimensions>;
204
- export declare function metricTriangleFromEmergence(points: readonly DiagnosticEmergencePoint<unknown>[], metricId: string): DiagnosticMetricTriangle;
205
- export declare function sameMaturity<TDimensions>(result: MetricDiagnosticsResult<TDimensions>, ageMonths: number, groups?: readonly string[]): DiagnosticEmergencePoint<TDimensions>[];
206
- export interface CommonMaturityResult<TDimensions = unknown> {
207
- ageMonths: number | null;
208
- points: DiagnosticEmergencePoint<TDimensions>[];
209
- }
210
- /** Latest maturity present in every selected group; selection is caller-defined. */
211
- export declare function commonMaturity<TDimensions>(result: MetricDiagnosticsResult<TDimensions>, groups: readonly string[]): CommonMaturityResult<TDimensions>;
212
- //# sourceMappingURL=metricDiagnostics.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"metricDiagnostics.d.ts","sourceRoot":"","sources":["../src/metricDiagnostics.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAkEpE,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,WAAW,CAAC;AAC9D,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC;AAEvF,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAA;CAAE,GAClD;IAAE,EAAE,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAE1E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EACA,mBAAmB,GACnB,sBAAsB,GACtB,sBAAsB,GACtB,mBAAmB,GACnB,qBAAqB,GACrB,qBAAqB,GACrB,sBAAsB,GACtB,wBAAwB,GACxB,uBAAuB,GACvB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,4FAA4F;AAC5F,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,iBAAiB,GAAG,iBAAiB,CAExF;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,IAAI,EAAE,oCAAoC,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,mBAAmB,GAAG,OAAO,GAAG,uBAAuB,GAAG,oBAAoB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACrG,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,iBAAiB,CAAC;IAC7B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,YAAY,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC5C,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,SAAS,iBAAiB,EAAE,CAAC;CACpF;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACpD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CAClD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,oBAAoB,EAAE,GAAG,gBAAgB,CAiBzF;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,SAAS,gBAAgB,EAAE,GAAG,gBAAgB,CAYhG;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,gBAAgB,EAC3B,YAAY,GAAE,iBAAmC,GAChD,iBAAiB,CA8BnB;AAED,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAMnF;AAqBD,wBAAgB,cAAc,CAC5B,UAAU,EAAE,gBAAgB,EAC5B,UAAU,EAAE,oBAAoB,EAChC,iBAAiB,GAAE,SAAS,iBAAiB,EAAO,GACnD,gBAAgB,CAmGlB;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,GAChD;IAAE,EAAE,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,eAAe,CAAC;IAC1B,kFAAkF;IAClF,KAAK,EAAE,qBAAqB,GAAG,iBAAiB,GAAG,oBAAoB,CAAC;CACzE;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,OAAO;IAC7C,UAAU,EAAE,CAAC,CAAC;IACd,QAAQ,EAAE,oBAAoB,CAAC;CAChC;AAyBD,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,IAAI,EAAE,SAAS,kBAAkB,CAAC,CAAC,CAAC,EAAE,EACtC,MAAM,EAAE,SAAS,qBAAqB,EAAE,GACvC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CASzB;AAED,MAAM,WAAW,iBAAiB,CAAC,WAAW,GAAG,OAAO;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,oBAAoB,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB,CAAC,WAAW,GAAG,OAAO;IAC1D,iFAAiF;IACjF,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB,CAAC,WAAW,GAAG,OAAO;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAC5B,KAAK,EAAE,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,uBAAuB,CAAC,WAAW,GAAG,OAAO;IAC5D,SAAS,EAAE,wBAAwB,CAAC,WAAW,CAAC,EAAE,CAAC;IACnD,SAAS,EAAE,wBAAwB,EAAE,CAAC;IACtC,cAAc,EAAE,wBAAwB,CAAC,WAAW,CAAC,EAAE,CAAC;CACzD;AAED,MAAM,WAAW,yBAAyB,CAAC,WAAW,GAAG,OAAO;IAC9D,MAAM,EAAE,SAAS,iBAAiB,CAAC,WAAW,CAAC,EAAE,CAAC;IAClD,SAAS,CAAC,EAAE,SAAS,qBAAqB,CAAC,WAAW,CAAC,EAAE,CAAC;IAC1D,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACrC,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,kDAAkD;IAClD,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;CACzD;AAyBD,MAAM,WAAW,uCAAuC;IACtD,IAAI,EAAE,wBAAwB,GAAG,sBAAsB,CAAC;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,6BAA6B,CAAC,WAAW,GAAG,OAAO;IAClE,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,EAAE,CAAC;IAChD,QAAQ,EAAE,uCAAuC,EAAE,CAAC;CACrD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,WAAW,GAAG,OAAO,EACnE,IAAI,EAAE,SAAS,qBAAqB,CAAC,WAAW,CAAC,EAAE,GAClD,6BAA6B,CAAC,WAAW,CAAC,CA2C5C;AAwGD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,GAAG,OAAO,EACxD,KAAK,EAAE,yBAAyB,CAAC,WAAW,CAAC,GAC5C,uBAAuB,CAAC,WAAW,CAAC,CAiHtC;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,SAAS,wBAAwB,CAAC,OAAO,CAAC,EAAE,EACpD,QAAQ,EAAE,MAAM,GACf,wBAAwB,CA6B1B;AAED,wBAAgB,YAAY,CAAC,WAAW,EACtC,MAAM,EAAE,uBAAuB,CAAC,WAAW,CAAC,EAC5C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GACzB,wBAAwB,CAAC,WAAW,CAAC,EAAE,CAIzC;AAED,MAAM,WAAW,oBAAoB,CAAC,WAAW,GAAG,OAAO;IACzD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,wBAAwB,CAAC,WAAW,CAAC,EAAE,CAAC;CACjD;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,WAAW,EACxC,MAAM,EAAE,uBAAuB,CAAC,WAAW,CAAC,EAC5C,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,oBAAoB,CAAC,WAAW,CAAC,CAcnC"}