@actuarial-ts/compliance 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/dist/bundle.d.ts +1 -1
- package/dist/bundle.js +1 -1
- package/dist/diagnostics.d.ts +75 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +44 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/bundle.ts +1 -1
- package/src/diagnostics.ts +104 -0
- package/src/index.ts +1 -0
package/README.md
CHANGED
|
@@ -22,6 +22,10 @@ Actuarial Standards of Practice ask for.
|
|
|
22
22
|
- **Reproducibility bundles** (ASOP 21 / 56): canonical serialization of
|
|
23
23
|
inputs, parameters, and results with an integrity tag, so an analysis
|
|
24
24
|
re-runs identically years later for an auditor or examiner.
|
|
25
|
+
- **Diagnostics provenance composition**: `createDiagnosticsProvenance`
|
|
26
|
+
snapshots formula-pack/metric versions, executable-definition metadata,
|
|
27
|
+
layer configuration, exposure basis and scale, sparse/age conventions,
|
|
28
|
+
cutoffs, caller-selected filters/groups, and caller-owned input IDs/hashes.
|
|
25
29
|
- **Actual-vs-expected roll-forward**: expected emergence from the prior
|
|
26
30
|
valuation's pattern versus actual, by origin.
|
|
27
31
|
|
|
@@ -65,11 +69,18 @@ const markdown = generateDisclosure({
|
|
|
65
69
|
{ methodId: "mack", basisLabel: "paid", resultSummary: { standardError: mack.totals.standardError } },
|
|
66
70
|
],
|
|
67
71
|
ledger,
|
|
68
|
-
sdkVersion: "0.
|
|
72
|
+
sdkVersion: "0.4.0",
|
|
69
73
|
generatedAt: "2026-01-05T10:15:00Z",
|
|
70
74
|
});
|
|
71
75
|
```
|
|
72
76
|
|
|
77
|
+
Diagnostic numeric results remain independent of this package. When an audit
|
|
78
|
+
record is needed, call `createDiagnosticsProvenance({ metrics, layers, ... })`
|
|
79
|
+
and place the returned plain record in `createBundle(...).parameters` or an
|
|
80
|
+
interchange document's `extensions`. Executable warning callbacks are excluded
|
|
81
|
+
from the record; their metric definition version is retained. Hashing,
|
|
82
|
+
timestamps, persistence, and signatures remain caller-owned.
|
|
83
|
+
|
|
73
84
|
## The honest claim
|
|
74
85
|
|
|
75
86
|
The ASB does not approve, certify, or endorse software, and no software can
|
package/dist/bundle.d.ts
CHANGED
|
@@ -65,7 +65,7 @@ export declare const WRAPPED_BUNDLE_INTERCHANGE_VERSION = "1.0.0";
|
|
|
65
65
|
* silently drift (mirroring interchange's INTERCHANGE_PACKAGE_VERSION
|
|
66
66
|
* discipline).
|
|
67
67
|
*/
|
|
68
|
-
export declare const COMPLIANCE_PACKAGE_VERSION = "0.
|
|
68
|
+
export declare const COMPLIANCE_PACKAGE_VERSION = "0.4.0";
|
|
69
69
|
/**
|
|
70
70
|
* The interchange mirror for a wrapped bundle (spec 3.2): the triangles the
|
|
71
71
|
* analysis consumed, the selections it applied, and the results it produced,
|
package/dist/bundle.js
CHANGED
|
@@ -60,7 +60,7 @@ export const WRAPPED_BUNDLE_INTERCHANGE_VERSION = "1.0.0";
|
|
|
60
60
|
* silently drift (mirroring interchange's INTERCHANGE_PACKAGE_VERSION
|
|
61
61
|
* discipline).
|
|
62
62
|
*/
|
|
63
|
-
export const COMPLIANCE_PACKAGE_VERSION = "0.
|
|
63
|
+
export const COMPLIANCE_PACKAGE_VERSION = "0.4.0";
|
|
64
64
|
export function createBundle(input) {
|
|
65
65
|
const body = {
|
|
66
66
|
createdAt: input.createdAt,
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { AmountLayerDefinition, MeasureExpression, MetricDefinition, SparseValuePolicy } from "@actuarial-ts/core";
|
|
2
|
+
/** Serializable metric metadata: executable warning callbacks are deliberately excluded. */
|
|
3
|
+
export interface DiagnosticMetricProvenance {
|
|
4
|
+
id: string;
|
|
5
|
+
definitionVersion: string;
|
|
6
|
+
displayName: string;
|
|
7
|
+
unit: string;
|
|
8
|
+
scale: number;
|
|
9
|
+
numerator: MeasureExpression;
|
|
10
|
+
denominator: MeasureExpression;
|
|
11
|
+
numeratorLabel: string;
|
|
12
|
+
denominatorLabel: string;
|
|
13
|
+
basis: string;
|
|
14
|
+
requiredComponents: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface DiagnosticLayerProvenance {
|
|
17
|
+
id: string;
|
|
18
|
+
displayName: string;
|
|
19
|
+
paidMeasure: string;
|
|
20
|
+
incurredMeasure: string;
|
|
21
|
+
paid: AmountLayerDefinition["paid"];
|
|
22
|
+
incurred: AmountLayerDefinition["incurred"];
|
|
23
|
+
basis: AmountLayerDefinition["basis"];
|
|
24
|
+
}
|
|
25
|
+
export interface CreateDiagnosticsProvenanceInput {
|
|
26
|
+
packageVersions: Readonly<Record<string, string>>;
|
|
27
|
+
formulaPack: {
|
|
28
|
+
id: string;
|
|
29
|
+
version: string;
|
|
30
|
+
};
|
|
31
|
+
metrics: readonly MetricDefinition[];
|
|
32
|
+
layers?: readonly AmountLayerDefinition[];
|
|
33
|
+
exposure: {
|
|
34
|
+
basis: string;
|
|
35
|
+
frequencyScale: number;
|
|
36
|
+
};
|
|
37
|
+
sparsePolicy: SparseValuePolicy;
|
|
38
|
+
ageConvention: string;
|
|
39
|
+
completePeriodCutoffs: Readonly<Record<string, string | number | boolean | null>>;
|
|
40
|
+
appliedFilters?: Readonly<Record<string, unknown>>;
|
|
41
|
+
groupingSelections?: Readonly<Record<string, unknown>>;
|
|
42
|
+
inputReferences: readonly {
|
|
43
|
+
id: string;
|
|
44
|
+
hash?: string;
|
|
45
|
+
}[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Audit metadata for a diagnostic run. This helper lives in compliance so
|
|
49
|
+
* core numeric results stay deterministic and free of application filter or
|
|
50
|
+
* persistence state. The returned record can be placed directly in
|
|
51
|
+
* `createBundle(...).parameters` or an interchange `extensions` object.
|
|
52
|
+
*/
|
|
53
|
+
export declare function createDiagnosticsProvenance(input: CreateDiagnosticsProvenanceInput): {
|
|
54
|
+
packageVersions: Record<string, string>;
|
|
55
|
+
formulaPack: {
|
|
56
|
+
id: string;
|
|
57
|
+
version: string;
|
|
58
|
+
};
|
|
59
|
+
metrics: DiagnosticMetricProvenance[];
|
|
60
|
+
layers: DiagnosticLayerProvenance[];
|
|
61
|
+
exposure: {
|
|
62
|
+
basis: string;
|
|
63
|
+
frequencyScale: number;
|
|
64
|
+
};
|
|
65
|
+
sparsePolicy: SparseValuePolicy;
|
|
66
|
+
ageConvention: string;
|
|
67
|
+
completePeriodCutoffs: Record<string, string | number | boolean | null>;
|
|
68
|
+
appliedFilters?: Record<string, unknown>;
|
|
69
|
+
groupingSelections?: Record<string, unknown>;
|
|
70
|
+
inputReferences: {
|
|
71
|
+
id: string;
|
|
72
|
+
hash?: string;
|
|
73
|
+
}[];
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit metadata for a diagnostic run. This helper lives in compliance so
|
|
3
|
+
* core numeric results stay deterministic and free of application filter or
|
|
4
|
+
* persistence state. The returned record can be placed directly in
|
|
5
|
+
* `createBundle(...).parameters` or an interchange `extensions` object.
|
|
6
|
+
*/
|
|
7
|
+
export function createDiagnosticsProvenance(input) {
|
|
8
|
+
const metrics = input.metrics.map((metric) => ({
|
|
9
|
+
id: metric.id,
|
|
10
|
+
definitionVersion: metric.version,
|
|
11
|
+
displayName: metric.displayName,
|
|
12
|
+
unit: metric.unit,
|
|
13
|
+
scale: metric.scale,
|
|
14
|
+
numerator: metric.numerator,
|
|
15
|
+
denominator: metric.denominator,
|
|
16
|
+
numeratorLabel: metric.numeratorLabel,
|
|
17
|
+
denominatorLabel: metric.denominatorLabel,
|
|
18
|
+
basis: metric.basis,
|
|
19
|
+
requiredComponents: [...metric.requiredComponents],
|
|
20
|
+
}));
|
|
21
|
+
const layers = (input.layers ?? []).map((layer) => ({
|
|
22
|
+
id: layer.id,
|
|
23
|
+
displayName: layer.displayName,
|
|
24
|
+
paidMeasure: layer.paidMeasure,
|
|
25
|
+
incurredMeasure: layer.incurredMeasure,
|
|
26
|
+
paid: layer.paid,
|
|
27
|
+
incurred: layer.incurred,
|
|
28
|
+
basis: layer.basis,
|
|
29
|
+
}));
|
|
30
|
+
return {
|
|
31
|
+
packageVersions: { ...input.packageVersions },
|
|
32
|
+
formulaPack: { ...input.formulaPack },
|
|
33
|
+
metrics,
|
|
34
|
+
layers,
|
|
35
|
+
exposure: { ...input.exposure },
|
|
36
|
+
sparsePolicy: input.sparsePolicy,
|
|
37
|
+
ageConvention: input.ageConvention,
|
|
38
|
+
completePeriodCutoffs: { ...input.completePeriodCutoffs },
|
|
39
|
+
...(input.appliedFilters ? { appliedFilters: { ...input.appliedFilters } } : {}),
|
|
40
|
+
...(input.groupingSelections ? { groupingSelections: { ...input.groupingSelections } } : {}),
|
|
41
|
+
inputReferences: input.inputReferences.map((reference) => ({ ...reference })),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AA8CA;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CACzC,KAAuC;IAcvC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7C,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,iBAAiB,EAAE,MAAM,CAAC,OAAO;QACjC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,kBAAkB,EAAE,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC;KACnD,CAAC,CAAC,CAAC;IACJ,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClD,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC,CAAC,CAAC;IACJ,OAAO;QACL,eAAe,EAAE,EAAE,GAAG,KAAK,CAAC,eAAe,EAAE;QAC7C,WAAW,EAAE,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE;QACrC,OAAO;QACP,MAAM;QACN,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE;QAC/B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,qBAAqB,EAAE,EAAE,GAAG,KAAK,CAAC,qBAAqB,EAAE;QACzD,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,GAAG,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,EAAE,GAAG,KAAK,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,eAAe,EAAE,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;KAC9E,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actuarial-ts/compliance",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "ASOP-compliance-support layer for the actuarial-ts SDK: estimate metadata, assumption ledger,
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "ASOP-compliance-support layer for the actuarial-ts SDK: estimate metadata, assumption ledger, disclosures, model cards, diagnostics provenance, reproducibility bundles, and actual-vs-expected roll-forward. Responsibility for compliance remains with the credentialed actuary.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"prepack": "tsc -p tsconfig.build.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@actuarial-ts/core": "^0.
|
|
50
|
-
"@actuarial-ts/interchange": "^0.
|
|
49
|
+
"@actuarial-ts/core": "^0.4.0",
|
|
50
|
+
"@actuarial-ts/interchange": "^0.4.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "^22.10.5",
|
package/src/bundle.ts
CHANGED
|
@@ -89,7 +89,7 @@ export const WRAPPED_BUNDLE_INTERCHANGE_VERSION = "1.0.0";
|
|
|
89
89
|
* silently drift (mirroring interchange's INTERCHANGE_PACKAGE_VERSION
|
|
90
90
|
* discipline).
|
|
91
91
|
*/
|
|
92
|
-
export const COMPLIANCE_PACKAGE_VERSION = "0.
|
|
92
|
+
export const COMPLIANCE_PACKAGE_VERSION = "0.4.0";
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
95
|
* The interchange mirror for a wrapped bundle (spec 3.2): the triangles the
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AmountLayerDefinition,
|
|
3
|
+
MeasureExpression,
|
|
4
|
+
MetricDefinition,
|
|
5
|
+
SparseValuePolicy,
|
|
6
|
+
} from "@actuarial-ts/core";
|
|
7
|
+
|
|
8
|
+
/** Serializable metric metadata: executable warning callbacks are deliberately excluded. */
|
|
9
|
+
export interface DiagnosticMetricProvenance {
|
|
10
|
+
id: string;
|
|
11
|
+
definitionVersion: string;
|
|
12
|
+
displayName: string;
|
|
13
|
+
unit: string;
|
|
14
|
+
scale: number;
|
|
15
|
+
numerator: MeasureExpression;
|
|
16
|
+
denominator: MeasureExpression;
|
|
17
|
+
numeratorLabel: string;
|
|
18
|
+
denominatorLabel: string;
|
|
19
|
+
basis: string;
|
|
20
|
+
requiredComponents: string[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface DiagnosticLayerProvenance {
|
|
24
|
+
id: string;
|
|
25
|
+
displayName: string;
|
|
26
|
+
paidMeasure: string;
|
|
27
|
+
incurredMeasure: string;
|
|
28
|
+
paid: AmountLayerDefinition["paid"];
|
|
29
|
+
incurred: AmountLayerDefinition["incurred"];
|
|
30
|
+
basis: AmountLayerDefinition["basis"];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface CreateDiagnosticsProvenanceInput {
|
|
34
|
+
packageVersions: Readonly<Record<string, string>>;
|
|
35
|
+
formulaPack: { id: string; version: string };
|
|
36
|
+
metrics: readonly MetricDefinition[];
|
|
37
|
+
layers?: readonly AmountLayerDefinition[];
|
|
38
|
+
exposure: { basis: string; frequencyScale: number };
|
|
39
|
+
sparsePolicy: SparseValuePolicy;
|
|
40
|
+
ageConvention: string;
|
|
41
|
+
completePeriodCutoffs: Readonly<Record<string, string | number | boolean | null>>;
|
|
42
|
+
appliedFilters?: Readonly<Record<string, unknown>>;
|
|
43
|
+
groupingSelections?: Readonly<Record<string, unknown>>;
|
|
44
|
+
inputReferences: readonly { id: string; hash?: string }[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Audit metadata for a diagnostic run. This helper lives in compliance so
|
|
49
|
+
* core numeric results stay deterministic and free of application filter or
|
|
50
|
+
* persistence state. The returned record can be placed directly in
|
|
51
|
+
* `createBundle(...).parameters` or an interchange `extensions` object.
|
|
52
|
+
*/
|
|
53
|
+
export function createDiagnosticsProvenance(
|
|
54
|
+
input: CreateDiagnosticsProvenanceInput,
|
|
55
|
+
): {
|
|
56
|
+
packageVersions: Record<string, string>;
|
|
57
|
+
formulaPack: { id: string; version: string };
|
|
58
|
+
metrics: DiagnosticMetricProvenance[];
|
|
59
|
+
layers: DiagnosticLayerProvenance[];
|
|
60
|
+
exposure: { basis: string; frequencyScale: number };
|
|
61
|
+
sparsePolicy: SparseValuePolicy;
|
|
62
|
+
ageConvention: string;
|
|
63
|
+
completePeriodCutoffs: Record<string, string | number | boolean | null>;
|
|
64
|
+
appliedFilters?: Record<string, unknown>;
|
|
65
|
+
groupingSelections?: Record<string, unknown>;
|
|
66
|
+
inputReferences: { id: string; hash?: string }[];
|
|
67
|
+
} {
|
|
68
|
+
const metrics = input.metrics.map((metric) => ({
|
|
69
|
+
id: metric.id,
|
|
70
|
+
definitionVersion: metric.version,
|
|
71
|
+
displayName: metric.displayName,
|
|
72
|
+
unit: metric.unit,
|
|
73
|
+
scale: metric.scale,
|
|
74
|
+
numerator: metric.numerator,
|
|
75
|
+
denominator: metric.denominator,
|
|
76
|
+
numeratorLabel: metric.numeratorLabel,
|
|
77
|
+
denominatorLabel: metric.denominatorLabel,
|
|
78
|
+
basis: metric.basis,
|
|
79
|
+
requiredComponents: [...metric.requiredComponents],
|
|
80
|
+
}));
|
|
81
|
+
const layers = (input.layers ?? []).map((layer) => ({
|
|
82
|
+
id: layer.id,
|
|
83
|
+
displayName: layer.displayName,
|
|
84
|
+
paidMeasure: layer.paidMeasure,
|
|
85
|
+
incurredMeasure: layer.incurredMeasure,
|
|
86
|
+
paid: layer.paid,
|
|
87
|
+
incurred: layer.incurred,
|
|
88
|
+
basis: layer.basis,
|
|
89
|
+
}));
|
|
90
|
+
return {
|
|
91
|
+
packageVersions: { ...input.packageVersions },
|
|
92
|
+
formulaPack: { ...input.formulaPack },
|
|
93
|
+
metrics,
|
|
94
|
+
layers,
|
|
95
|
+
exposure: { ...input.exposure },
|
|
96
|
+
sparsePolicy: input.sparsePolicy,
|
|
97
|
+
ageConvention: input.ageConvention,
|
|
98
|
+
completePeriodCutoffs: { ...input.completePeriodCutoffs },
|
|
99
|
+
...(input.appliedFilters ? { appliedFilters: { ...input.appliedFilters } } : {}),
|
|
100
|
+
...(input.groupingSelections ? { groupingSelections: { ...input.groupingSelections } } : {}),
|
|
101
|
+
inputReferences: input.inputReferences.map((reference) => ({ ...reference })),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|