@actuarial-ts/agents 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.
- package/README.md +32 -128
- package/dist/diagnostics.d.ts +69 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +655 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/divergence.d.ts +4 -3
- package/dist/divergence.d.ts.map +1 -1
- package/dist/divergence.js +30 -10
- package/dist/divergence.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +7 -0
- package/dist/errors.js.map +1 -1
- 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/dist/judgment.d.ts +75 -2
- package/dist/judgment.d.ts.map +1 -1
- package/dist/judgment.js +28 -10
- package/dist/judgment.js.map +1 -1
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +2 -2
- package/dist/promotion.d.ts.map +1 -1
- package/dist/promotion.js +2 -0
- package/dist/promotion.js.map +1 -1
- package/dist/remote.d.ts +7 -9
- package/dist/remote.d.ts.map +1 -1
- package/dist/tools.d.ts +26 -12
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +132 -23
- package/dist/tools.js.map +1 -1
- package/package.json +12 -11
- package/src/diagnostics.ts +833 -0
- package/src/divergence.ts +73 -29
- package/src/errors.ts +7 -0
- package/src/index.ts +1 -0
- package/src/judgment.ts +56 -20
- package/src/mcp.ts +2 -2
- package/src/promotion.ts +2 -0
- package/src/tools.ts +351 -54
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
import { assertCompiledDiagnosticDefinition, isDiagnosticToken, isDiagnosticPlainRecord, } from "@actuarial-ts/core";
|
|
2
|
+
import { assertVerifiedDiagnosticRunProvenance, } from "@actuarial-ts/compliance";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { AgentsError } from "./errors.js";
|
|
5
|
+
import { defineActuarialTool, } from "./tools.js";
|
|
6
|
+
const tokenSchema = z.string().min(1).refine(isDiagnosticToken);
|
|
7
|
+
const selectedInstanceIdsSchema = z
|
|
8
|
+
.array(tokenSchema)
|
|
9
|
+
.min(1);
|
|
10
|
+
export const diagnosticAgentToolInputSchema = z
|
|
11
|
+
.object({
|
|
12
|
+
runPresetId: tokenSchema,
|
|
13
|
+
instanceIds: selectedInstanceIdsSchema,
|
|
14
|
+
view: z.enum(["emergence", "triangles", "latest-diagonal"]),
|
|
15
|
+
})
|
|
16
|
+
.strict();
|
|
17
|
+
const toolFailureSchema = z
|
|
18
|
+
.object({
|
|
19
|
+
success: z.literal(false),
|
|
20
|
+
error: z.object({ code: z.string(), message: z.string() }).strict(),
|
|
21
|
+
})
|
|
22
|
+
.strict();
|
|
23
|
+
const tagSchema = z.string().regex(/^fnv1a64-jcs-v1:[0-9a-f]{16}$/);
|
|
24
|
+
const finiteNullable = z.number().finite().nullable();
|
|
25
|
+
/** Zod 3 drops an own `__proto__` key when assembling records. Encode every
|
|
26
|
+
* key during validation and decode only after its value has been validated. */
|
|
27
|
+
function recordSchema(valueSchema) {
|
|
28
|
+
return z
|
|
29
|
+
.record(z.string().transform((key) => `:${key}`), valueSchema)
|
|
30
|
+
.transform((record) => Object.fromEntries(Object.entries(record).map(([key, value]) => [key.slice(1), value])));
|
|
31
|
+
}
|
|
32
|
+
const jsonSchema = z.lazy(() => z.union([
|
|
33
|
+
z.string(),
|
|
34
|
+
z.number().finite(),
|
|
35
|
+
z.boolean(),
|
|
36
|
+
z.null(),
|
|
37
|
+
z.array(jsonSchema),
|
|
38
|
+
recordSchema(jsonSchema),
|
|
39
|
+
]));
|
|
40
|
+
const sourceSchema = z
|
|
41
|
+
.object({
|
|
42
|
+
artifactId: tokenSchema,
|
|
43
|
+
sourceFile: tokenSchema.optional(),
|
|
44
|
+
sourceSheet: tokenSchema.optional(),
|
|
45
|
+
sourceRow: z.number().int().nonnegative().optional(),
|
|
46
|
+
sourceCell: tokenSchema.optional(),
|
|
47
|
+
})
|
|
48
|
+
.strict();
|
|
49
|
+
const quantitySchema = z
|
|
50
|
+
.object({
|
|
51
|
+
kind: z.enum(["amount", "count", "exposure"]),
|
|
52
|
+
unit: tokenSchema,
|
|
53
|
+
basisId: tokenSchema.optional(),
|
|
54
|
+
countPopulationId: tokenSchema.optional(),
|
|
55
|
+
exposureBasisId: tokenSchema.optional(),
|
|
56
|
+
value: finiteNullable,
|
|
57
|
+
})
|
|
58
|
+
.strict();
|
|
59
|
+
const statsSchema = z
|
|
60
|
+
.object({
|
|
61
|
+
sum: finiteNullable,
|
|
62
|
+
value: finiteNullable,
|
|
63
|
+
observed: z.number().int().nonnegative(),
|
|
64
|
+
missing: z.number().int().nonnegative(),
|
|
65
|
+
imputedZero: z.number().int().nonnegative(),
|
|
66
|
+
nonFinite: z.number().int().nonnegative(),
|
|
67
|
+
structural: z.number().int().nonnegative(),
|
|
68
|
+
deduplicated: z.number().int().nonnegative(),
|
|
69
|
+
})
|
|
70
|
+
.strict();
|
|
71
|
+
const findingSchema = z
|
|
72
|
+
.object({
|
|
73
|
+
code: tokenSchema,
|
|
74
|
+
message: z.string().min(1),
|
|
75
|
+
severity: z.enum(["info", "warning", "fail"]),
|
|
76
|
+
category: z.enum([
|
|
77
|
+
"structural",
|
|
78
|
+
"aggregation",
|
|
79
|
+
"calculation",
|
|
80
|
+
"rule",
|
|
81
|
+
"presentation",
|
|
82
|
+
]),
|
|
83
|
+
ruleId: tokenSchema.optional(),
|
|
84
|
+
measureId: tokenSchema.optional(),
|
|
85
|
+
instanceId: tokenSchema.optional(),
|
|
86
|
+
expressionPath: z.string().optional(),
|
|
87
|
+
offendingKey: z.string().optional(),
|
|
88
|
+
sourceGroup: tokenSchema.optional(),
|
|
89
|
+
group: tokenSchema.optional(),
|
|
90
|
+
origin: tokenSchema.optional(),
|
|
91
|
+
valuation: tokenSchema.optional(),
|
|
92
|
+
developmentAge: z.number().int().nonnegative().optional(),
|
|
93
|
+
ageUnit: tokenSchema.optional(),
|
|
94
|
+
recordId: tokenSchema.optional(),
|
|
95
|
+
claimId: tokenSchema.optional(),
|
|
96
|
+
exposureKey: tokenSchema.optional(),
|
|
97
|
+
sources: z.array(sourceSchema),
|
|
98
|
+
})
|
|
99
|
+
.strict();
|
|
100
|
+
const overflowSchema = z
|
|
101
|
+
.object({ expressionPath: z.string(), sources: z.array(sourceSchema) })
|
|
102
|
+
.strict();
|
|
103
|
+
const metricRuleSchema = z
|
|
104
|
+
.object({
|
|
105
|
+
ruleId: tokenSchema,
|
|
106
|
+
status: z.enum(["pass", "triggered", "not-evaluated"]),
|
|
107
|
+
severity: z.enum(["warning", "fail"]),
|
|
108
|
+
left: finiteNullable,
|
|
109
|
+
right: finiteNullable,
|
|
110
|
+
relation: z.enum(["less", "equal", "greater"]).nullable(),
|
|
111
|
+
notEvaluatedReasons: z.array(z.enum([
|
|
112
|
+
"missing",
|
|
113
|
+
"imputed",
|
|
114
|
+
"non-finite",
|
|
115
|
+
"structural-ambiguity",
|
|
116
|
+
"aggregation-overflow",
|
|
117
|
+
"expression-overflow",
|
|
118
|
+
"tolerance-overflow",
|
|
119
|
+
])),
|
|
120
|
+
expressionOverflows: z.array(overflowSchema),
|
|
121
|
+
code: z.string().nullable(),
|
|
122
|
+
message: z.string().nullable(),
|
|
123
|
+
})
|
|
124
|
+
.strict();
|
|
125
|
+
const presentationSchema = z
|
|
126
|
+
.object({
|
|
127
|
+
displayName: z.string().min(1),
|
|
128
|
+
description: z.string().min(1),
|
|
129
|
+
displayUnit: tokenSchema,
|
|
130
|
+
scale: z.number().finite().positive(),
|
|
131
|
+
numeratorLabel: z.string().min(1),
|
|
132
|
+
denominatorLabel: z.string().min(1),
|
|
133
|
+
value: finiteNullable,
|
|
134
|
+
})
|
|
135
|
+
.strict();
|
|
136
|
+
const evaluationSchema = z
|
|
137
|
+
.object({
|
|
138
|
+
instanceId: tokenSchema,
|
|
139
|
+
instanceVersion: tokenSchema,
|
|
140
|
+
formulaId: tokenSchema,
|
|
141
|
+
formulaVersion: tokenSchema,
|
|
142
|
+
semanticReferences: z
|
|
143
|
+
.object({
|
|
144
|
+
amountBasisIds: z.array(tokenSchema),
|
|
145
|
+
countPopulationIds: z.array(tokenSchema),
|
|
146
|
+
exposureBasisIds: z.array(tokenSchema),
|
|
147
|
+
})
|
|
148
|
+
.strict(),
|
|
149
|
+
formulaFingerprint: tagSchema,
|
|
150
|
+
calculationFingerprint: tagSchema,
|
|
151
|
+
definitionIntegrity: tagSchema,
|
|
152
|
+
calculation: z
|
|
153
|
+
.object({
|
|
154
|
+
numerator: quantitySchema,
|
|
155
|
+
denominator: quantitySchema,
|
|
156
|
+
value: finiteNullable,
|
|
157
|
+
})
|
|
158
|
+
.strict(),
|
|
159
|
+
presentation: presentationSchema,
|
|
160
|
+
components: recordSchema(statsSchema),
|
|
161
|
+
rules: z.array(metricRuleSchema),
|
|
162
|
+
findings: z.array(findingSchema),
|
|
163
|
+
})
|
|
164
|
+
.strict();
|
|
165
|
+
const pointSchema = z
|
|
166
|
+
.object({
|
|
167
|
+
group: tokenSchema,
|
|
168
|
+
sourceGroups: z.array(tokenSchema),
|
|
169
|
+
dimensions: jsonSchema.optional(),
|
|
170
|
+
origin: tokenSchema,
|
|
171
|
+
valuation: tokenSchema,
|
|
172
|
+
developmentAge: z.number().int().nonnegative(),
|
|
173
|
+
ageUnit: tokenSchema,
|
|
174
|
+
components: recordSchema(statsSchema),
|
|
175
|
+
metrics: recordSchema(evaluationSchema),
|
|
176
|
+
findings: z.array(findingSchema),
|
|
177
|
+
})
|
|
178
|
+
.strict();
|
|
179
|
+
const triangleCellSchema = z
|
|
180
|
+
.object({
|
|
181
|
+
origin: tokenSchema,
|
|
182
|
+
valuation: tokenSchema,
|
|
183
|
+
developmentAge: z.number().int().nonnegative(),
|
|
184
|
+
ageUnit: tokenSchema,
|
|
185
|
+
evaluation: evaluationSchema,
|
|
186
|
+
})
|
|
187
|
+
.strict();
|
|
188
|
+
const triangleSchema = z
|
|
189
|
+
.object({
|
|
190
|
+
group: tokenSchema,
|
|
191
|
+
instanceId: tokenSchema,
|
|
192
|
+
origins: z.array(tokenSchema),
|
|
193
|
+
developmentAges: z.array(z.number().int().nonnegative()),
|
|
194
|
+
ageUnit: tokenSchema,
|
|
195
|
+
calculationValues: z.array(z.array(finiteNullable)),
|
|
196
|
+
presentationValues: z.array(z.array(finiteNullable)),
|
|
197
|
+
cells: z.array(z.array(triangleCellSchema.nullable())),
|
|
198
|
+
})
|
|
199
|
+
.strict();
|
|
200
|
+
const reviewCoordinateSchema = z
|
|
201
|
+
.object({
|
|
202
|
+
sourceGroup: tokenSchema,
|
|
203
|
+
origin: tokenSchema,
|
|
204
|
+
valuation: tokenSchema,
|
|
205
|
+
developmentAge: z.number().int().nonnegative().safe(),
|
|
206
|
+
ageUnit: tokenSchema,
|
|
207
|
+
})
|
|
208
|
+
.strict();
|
|
209
|
+
const cellReviewScopeSchema = z
|
|
210
|
+
.object({
|
|
211
|
+
kind: z.literal("cell"),
|
|
212
|
+
cell: reviewCoordinateSchema,
|
|
213
|
+
sources: z.array(sourceSchema),
|
|
214
|
+
})
|
|
215
|
+
.strict();
|
|
216
|
+
const pairReviewScopeSchema = z
|
|
217
|
+
.object({
|
|
218
|
+
kind: z.literal("valuation-pair"),
|
|
219
|
+
previous: reviewCoordinateSchema,
|
|
220
|
+
current: reviewCoordinateSchema,
|
|
221
|
+
sources: z.array(sourceSchema),
|
|
222
|
+
})
|
|
223
|
+
.strict();
|
|
224
|
+
const controlReviewScopeSchema = z
|
|
225
|
+
.object({
|
|
226
|
+
kind: z.literal("control-total"),
|
|
227
|
+
projection: z.discriminatedUnion("kind", [
|
|
228
|
+
z
|
|
229
|
+
.object({ kind: z.literal("valuation"), valuation: tokenSchema })
|
|
230
|
+
.strict(),
|
|
231
|
+
z.object({ kind: z.literal("latest-valuation-per-origin") }).strict(),
|
|
232
|
+
z.object({ kind: z.literal("all-cells") }).strict(),
|
|
233
|
+
]),
|
|
234
|
+
filter: z
|
|
235
|
+
.object({
|
|
236
|
+
sourceGroups: z.array(tokenSchema).nullable(),
|
|
237
|
+
origins: z.array(tokenSchema).nullable(),
|
|
238
|
+
originFrom: tokenSchema.nullable(),
|
|
239
|
+
originThrough: tokenSchema.nullable(),
|
|
240
|
+
valuations: z.array(tokenSchema).nullable(),
|
|
241
|
+
valuationFrom: tokenSchema.nullable(),
|
|
242
|
+
valuationThrough: tokenSchema.nullable(),
|
|
243
|
+
minDevelopmentAge: z.number().int().nonnegative().safe().nullable(),
|
|
244
|
+
maxDevelopmentAge: z.number().int().nonnegative().safe().nullable(),
|
|
245
|
+
})
|
|
246
|
+
.strict()
|
|
247
|
+
.nullable(),
|
|
248
|
+
selectedCellCount: z.number().int().nonnegative().safe(),
|
|
249
|
+
selectedContributionCount: z.number().int().nonnegative().safe(),
|
|
250
|
+
sources: z.array(sourceSchema),
|
|
251
|
+
})
|
|
252
|
+
.strict();
|
|
253
|
+
const reviewScopeSchema = z.discriminatedUnion("kind", [
|
|
254
|
+
cellReviewScopeSchema,
|
|
255
|
+
pairReviewScopeSchema,
|
|
256
|
+
controlReviewScopeSchema,
|
|
257
|
+
]);
|
|
258
|
+
const dataFindingContextSchema = z
|
|
259
|
+
.object({
|
|
260
|
+
ruleId: tokenSchema.optional(),
|
|
261
|
+
measureId: tokenSchema.optional(),
|
|
262
|
+
expressionPath: z.string().optional(),
|
|
263
|
+
offendingKey: z.string().optional(),
|
|
264
|
+
groupingKey: tokenSchema.optional(),
|
|
265
|
+
cachedEvidenceId: tokenSchema.optional(),
|
|
266
|
+
sourceGroup: tokenSchema.optional(),
|
|
267
|
+
origin: tokenSchema.optional(),
|
|
268
|
+
valuation: tokenSchema.optional(),
|
|
269
|
+
developmentAge: z.number().int().nonnegative().safe().optional(),
|
|
270
|
+
ageUnit: tokenSchema.optional(),
|
|
271
|
+
recordId: tokenSchema.optional(),
|
|
272
|
+
claimId: tokenSchema.optional(),
|
|
273
|
+
exposureKey: tokenSchema.optional(),
|
|
274
|
+
group: tokenSchema.optional(),
|
|
275
|
+
sourceFile: tokenSchema.optional(),
|
|
276
|
+
sourceRow: z.number().int().nonnegative().safe().optional(),
|
|
277
|
+
sources: z.array(sourceSchema).optional(),
|
|
278
|
+
reviewScope: reviewScopeSchema.optional(),
|
|
279
|
+
})
|
|
280
|
+
.strict();
|
|
281
|
+
const dataFindingSchema = z
|
|
282
|
+
.object({
|
|
283
|
+
code: tokenSchema,
|
|
284
|
+
message: z.string(),
|
|
285
|
+
context: dataFindingContextSchema.optional(),
|
|
286
|
+
})
|
|
287
|
+
.strict();
|
|
288
|
+
const reviewEvaluationBaseSchema = z
|
|
289
|
+
.object({
|
|
290
|
+
ruleId: tokenSchema,
|
|
291
|
+
status: z.enum(["pass", "triggered", "not-evaluated"]),
|
|
292
|
+
severity: z.enum(["warning", "fail"]),
|
|
293
|
+
triggerReason: z
|
|
294
|
+
.enum([
|
|
295
|
+
"predicate",
|
|
296
|
+
"missing-input",
|
|
297
|
+
"aggregation-overflow",
|
|
298
|
+
"expression-overflow",
|
|
299
|
+
"tolerance-overflow",
|
|
300
|
+
])
|
|
301
|
+
.nullable(),
|
|
302
|
+
left: finiteNullable,
|
|
303
|
+
right: finiteNullable,
|
|
304
|
+
relation: z.enum(["less", "equal", "greater"]).nullable(),
|
|
305
|
+
notEvaluatedReasons: metricRuleSchema.shape.notEvaluatedReasons,
|
|
306
|
+
expressionOverflows: z.array(overflowSchema.extend({ coordinate: reviewCoordinateSchema.nullable() })),
|
|
307
|
+
})
|
|
308
|
+
.strict();
|
|
309
|
+
const comparabilitySchema = z.discriminatedUnion("kind", [
|
|
310
|
+
z.object({ kind: z.literal("compiler-proven") }).strict(),
|
|
311
|
+
z
|
|
312
|
+
.object({
|
|
313
|
+
kind: z.literal("caller-asserted"),
|
|
314
|
+
rationaleArtifactId: tokenSchema,
|
|
315
|
+
})
|
|
316
|
+
.strict(),
|
|
317
|
+
]);
|
|
318
|
+
const reviewEvaluationSchema = z.discriminatedUnion("ruleKind", [
|
|
319
|
+
reviewEvaluationBaseSchema.extend({
|
|
320
|
+
ruleKind: z.literal("compare"),
|
|
321
|
+
scope: cellReviewScopeSchema,
|
|
322
|
+
}),
|
|
323
|
+
reviewEvaluationBaseSchema.extend({
|
|
324
|
+
ruleKind: z.literal("reconcile"),
|
|
325
|
+
scope: cellReviewScopeSchema,
|
|
326
|
+
}),
|
|
327
|
+
reviewEvaluationBaseSchema.extend({
|
|
328
|
+
ruleKind: z.literal("monotonic"),
|
|
329
|
+
scope: pairReviewScopeSchema,
|
|
330
|
+
}),
|
|
331
|
+
reviewEvaluationBaseSchema.extend({
|
|
332
|
+
ruleKind: z.literal("control-total"),
|
|
333
|
+
scope: controlReviewScopeSchema,
|
|
334
|
+
}),
|
|
335
|
+
reviewEvaluationBaseSchema.extend({
|
|
336
|
+
ruleKind: z.literal("layer-order"),
|
|
337
|
+
scope: cellReviewScopeSchema,
|
|
338
|
+
comparability: comparabilitySchema,
|
|
339
|
+
}),
|
|
340
|
+
]);
|
|
341
|
+
const reviewSchemaBase = z
|
|
342
|
+
.object({
|
|
343
|
+
definitionIntegrity: tagSchema,
|
|
344
|
+
preparationFingerprint: tagSchema,
|
|
345
|
+
report: z
|
|
346
|
+
.object({
|
|
347
|
+
checks: z.array(z
|
|
348
|
+
.object({
|
|
349
|
+
id: tokenSchema,
|
|
350
|
+
description: z.string(),
|
|
351
|
+
status: z.enum(["pass", "warning", "fail", "not-evaluated"]),
|
|
352
|
+
details: z.array(z.string()),
|
|
353
|
+
findings: z.array(dataFindingSchema),
|
|
354
|
+
})
|
|
355
|
+
.strict()),
|
|
356
|
+
summary: z
|
|
357
|
+
.object({
|
|
358
|
+
pass: z.number().int().nonnegative(),
|
|
359
|
+
warning: z.number().int().nonnegative(),
|
|
360
|
+
fail: z.number().int().nonnegative(),
|
|
361
|
+
notEvaluated: z.number().int().nonnegative(),
|
|
362
|
+
})
|
|
363
|
+
.strict(),
|
|
364
|
+
})
|
|
365
|
+
.strict(),
|
|
366
|
+
evaluations: z.array(reviewEvaluationSchema),
|
|
367
|
+
evidence: z
|
|
368
|
+
.object({
|
|
369
|
+
groupingAssignments: z.array(z
|
|
370
|
+
.object({
|
|
371
|
+
key: tokenSchema,
|
|
372
|
+
group: tokenSchema,
|
|
373
|
+
source: sourceSchema.optional(),
|
|
374
|
+
})
|
|
375
|
+
.strict()),
|
|
376
|
+
cachedFormulas: z.array(z
|
|
377
|
+
.object({
|
|
378
|
+
id: tokenSchema,
|
|
379
|
+
source: sourceSchema.optional(),
|
|
380
|
+
formula: z.string().optional(),
|
|
381
|
+
cachedValue: finiteNullable.optional(),
|
|
382
|
+
declaredFormulaSource: z.boolean(),
|
|
383
|
+
})
|
|
384
|
+
.strict()),
|
|
385
|
+
})
|
|
386
|
+
.strict()
|
|
387
|
+
.nullable(),
|
|
388
|
+
reportFingerprint: tagSchema,
|
|
389
|
+
})
|
|
390
|
+
.strict();
|
|
391
|
+
const normalizedSourceSchema = sourceSchema.extend({
|
|
392
|
+
sourceFile: tokenSchema.nullable(),
|
|
393
|
+
sourceSheet: tokenSchema.nullable(),
|
|
394
|
+
sourceRow: z.number().int().nonnegative().safe().nullable(),
|
|
395
|
+
sourceCell: tokenSchema.nullable(),
|
|
396
|
+
});
|
|
397
|
+
const normalizedSourcesSchema = z.array(normalizedSourceSchema);
|
|
398
|
+
const normalizedCellScopeSchema = cellReviewScopeSchema.extend({
|
|
399
|
+
sources: normalizedSourcesSchema,
|
|
400
|
+
});
|
|
401
|
+
const normalizedPairScopeSchema = pairReviewScopeSchema.extend({
|
|
402
|
+
sources: normalizedSourcesSchema,
|
|
403
|
+
});
|
|
404
|
+
const normalizedControlScopeSchema = controlReviewScopeSchema.extend({
|
|
405
|
+
sources: normalizedSourcesSchema,
|
|
406
|
+
});
|
|
407
|
+
const normalizedScopeSchema = z.discriminatedUnion("kind", [
|
|
408
|
+
normalizedCellScopeSchema,
|
|
409
|
+
normalizedPairScopeSchema,
|
|
410
|
+
normalizedControlScopeSchema,
|
|
411
|
+
]);
|
|
412
|
+
const normalizedReviewEvaluationBaseSchema = reviewEvaluationBaseSchema.extend({
|
|
413
|
+
expressionOverflows: z.array(overflowSchema.extend({
|
|
414
|
+
sources: normalizedSourcesSchema,
|
|
415
|
+
coordinate: reviewCoordinateSchema.nullable(),
|
|
416
|
+
})),
|
|
417
|
+
});
|
|
418
|
+
const normalizedReviewEvaluationSchema = z.discriminatedUnion("ruleKind", [
|
|
419
|
+
normalizedReviewEvaluationBaseSchema.extend({
|
|
420
|
+
ruleKind: z.literal("compare"),
|
|
421
|
+
scope: normalizedCellScopeSchema,
|
|
422
|
+
}),
|
|
423
|
+
normalizedReviewEvaluationBaseSchema.extend({
|
|
424
|
+
ruleKind: z.literal("reconcile"),
|
|
425
|
+
scope: normalizedCellScopeSchema,
|
|
426
|
+
}),
|
|
427
|
+
normalizedReviewEvaluationBaseSchema.extend({
|
|
428
|
+
ruleKind: z.literal("monotonic"),
|
|
429
|
+
scope: normalizedPairScopeSchema,
|
|
430
|
+
}),
|
|
431
|
+
normalizedReviewEvaluationBaseSchema.extend({
|
|
432
|
+
ruleKind: z.literal("control-total"),
|
|
433
|
+
scope: normalizedControlScopeSchema,
|
|
434
|
+
}),
|
|
435
|
+
normalizedReviewEvaluationBaseSchema.extend({
|
|
436
|
+
ruleKind: z.literal("layer-order"),
|
|
437
|
+
scope: normalizedCellScopeSchema,
|
|
438
|
+
comparability: comparabilitySchema,
|
|
439
|
+
}),
|
|
440
|
+
]);
|
|
441
|
+
const normalizedFindingSchema = dataFindingSchema.extend({
|
|
442
|
+
context: dataFindingContextSchema
|
|
443
|
+
.extend({
|
|
444
|
+
sources: normalizedSourcesSchema.optional(),
|
|
445
|
+
reviewScope: normalizedScopeSchema.optional(),
|
|
446
|
+
})
|
|
447
|
+
.optional(),
|
|
448
|
+
});
|
|
449
|
+
const evidenceShape = reviewSchemaBase.shape.evidence.unwrap().shape;
|
|
450
|
+
const normalizedEvidenceSchema = z
|
|
451
|
+
.object({
|
|
452
|
+
groupingAssignments: z.array(evidenceShape.groupingAssignments.element.extend({
|
|
453
|
+
source: normalizedSourceSchema.optional(),
|
|
454
|
+
})),
|
|
455
|
+
cachedFormulas: z.array(evidenceShape.cachedFormulas.element.extend({
|
|
456
|
+
source: normalizedSourceSchema.optional(),
|
|
457
|
+
})),
|
|
458
|
+
})
|
|
459
|
+
.strict()
|
|
460
|
+
.nullable();
|
|
461
|
+
const reviewSchema = reviewSchemaBase.extend({
|
|
462
|
+
identityBody: z
|
|
463
|
+
.object({
|
|
464
|
+
definitionIntegrity: tagSchema,
|
|
465
|
+
preparationFingerprint: tagSchema,
|
|
466
|
+
evidence: normalizedEvidenceSchema,
|
|
467
|
+
checks: z.array(reviewSchemaBase.shape.report.shape.checks.element
|
|
468
|
+
.omit({ description: true, details: true })
|
|
469
|
+
.extend({ findings: z.array(normalizedFindingSchema) })),
|
|
470
|
+
summary: reviewSchemaBase.shape.report.shape.summary,
|
|
471
|
+
evaluations: z.array(normalizedReviewEvaluationSchema),
|
|
472
|
+
})
|
|
473
|
+
.strict(),
|
|
474
|
+
});
|
|
475
|
+
const displaySchema = z.discriminatedUnion("view", [
|
|
476
|
+
z
|
|
477
|
+
.object({
|
|
478
|
+
view: z.literal("emergence"),
|
|
479
|
+
points: z.array(pointSchema.omit({ components: true })),
|
|
480
|
+
})
|
|
481
|
+
.strict(),
|
|
482
|
+
z
|
|
483
|
+
.object({
|
|
484
|
+
view: z.literal("triangles"),
|
|
485
|
+
triangles: z.array(triangleSchema),
|
|
486
|
+
})
|
|
487
|
+
.strict(),
|
|
488
|
+
z
|
|
489
|
+
.object({
|
|
490
|
+
view: z.literal("latest-diagonal"),
|
|
491
|
+
points: z.array(pointSchema.omit({ components: true })),
|
|
492
|
+
})
|
|
493
|
+
.strict(),
|
|
494
|
+
]);
|
|
495
|
+
const toolSuccessSchema = z
|
|
496
|
+
.object({
|
|
497
|
+
success: z.literal(true),
|
|
498
|
+
data: z
|
|
499
|
+
.object({
|
|
500
|
+
runPresetId: tokenSchema,
|
|
501
|
+
instanceIds: z.array(tokenSchema).min(1),
|
|
502
|
+
definitionIntegrity: tagSchema,
|
|
503
|
+
formulaFingerprints: recordSchema(tagSchema),
|
|
504
|
+
calculationFingerprints: recordSchema(tagSchema),
|
|
505
|
+
runFingerprint: tagSchema,
|
|
506
|
+
resultFingerprint: tagSchema,
|
|
507
|
+
runResultFingerprint: tagSchema,
|
|
508
|
+
review: reviewSchema,
|
|
509
|
+
display: displaySchema,
|
|
510
|
+
})
|
|
511
|
+
.strict(),
|
|
512
|
+
})
|
|
513
|
+
.strict();
|
|
514
|
+
/** Strict model-visible output schema, including the wrapper's failure branch. */
|
|
515
|
+
export const diagnosticAgentToolResultSchema = z.union([
|
|
516
|
+
toolSuccessSchema,
|
|
517
|
+
toolFailureSchema,
|
|
518
|
+
]);
|
|
519
|
+
function token(value, label) {
|
|
520
|
+
if (!isDiagnosticToken(value))
|
|
521
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", `${label} must be a nonempty token`);
|
|
522
|
+
}
|
|
523
|
+
function sortUniqueRequested(values) {
|
|
524
|
+
const result = [...new Set(values)];
|
|
525
|
+
result.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
526
|
+
return result;
|
|
527
|
+
}
|
|
528
|
+
export function createDiagnosticSelectionTool(input) {
|
|
529
|
+
try {
|
|
530
|
+
assertCompiledDiagnosticDefinition(input.definition);
|
|
531
|
+
}
|
|
532
|
+
catch {
|
|
533
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", "definition must be an authentic compiled diagnostic definition");
|
|
534
|
+
}
|
|
535
|
+
const definition = input.definition;
|
|
536
|
+
const id = input.id === undefined ? "run_diagnostic_selection" : input.id;
|
|
537
|
+
const description = input.description === undefined
|
|
538
|
+
? "Run a host-approved diagnostic preset for selected registered metric instances."
|
|
539
|
+
: input.description;
|
|
540
|
+
const tenantKey = input.tenantContextKey === undefined ? "projectId" : input.tenantContextKey;
|
|
541
|
+
token(id, "tool id");
|
|
542
|
+
token(tenantKey, "tenant context key");
|
|
543
|
+
if (typeof description !== "string" || description.trim().length === 0)
|
|
544
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", "description must be nonblank");
|
|
545
|
+
if (!Array.isArray(input.runPresets) || input.runPresets.length === 0)
|
|
546
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", "at least one approved diagnostic preset is required");
|
|
547
|
+
const known = new Set(definition.definition.instances.map((item) => item.id));
|
|
548
|
+
const catalog = new Map();
|
|
549
|
+
for (const preset of input.runPresets) {
|
|
550
|
+
if (!isDiagnosticPlainRecord(preset))
|
|
551
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", "Each diagnostic preset must be a plain record");
|
|
552
|
+
token(preset.id, "preset id");
|
|
553
|
+
if (catalog.has(preset.id))
|
|
554
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", `duplicate preset ${preset.id}`);
|
|
555
|
+
if (preset.definitionIntegrity !== definition.definitionIntegrity)
|
|
556
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", `preset ${preset.id} targets another definition`);
|
|
557
|
+
if (typeof preset.execute !== "function")
|
|
558
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", `preset ${preset.id} has no executor`);
|
|
559
|
+
const seen = new Set();
|
|
560
|
+
if (!Array.isArray(preset.allowedInstanceIds))
|
|
561
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", `preset ${preset.id} must declare allowed instance IDs`);
|
|
562
|
+
for (const instanceId of preset.allowedInstanceIds) {
|
|
563
|
+
token(instanceId, "allowed instance id");
|
|
564
|
+
if (seen.has(instanceId))
|
|
565
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", `preset ${preset.id} repeats ${instanceId}`);
|
|
566
|
+
if (!known.has(instanceId))
|
|
567
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", `preset ${preset.id} references unknown instance ${instanceId}`);
|
|
568
|
+
seen.add(instanceId);
|
|
569
|
+
}
|
|
570
|
+
if (seen.size === 0)
|
|
571
|
+
throw new AgentsError("BAD_DIAGNOSTIC_CATALOG", `preset ${preset.id} has no allowed instances`);
|
|
572
|
+
catalog.set(preset.id, Object.freeze({
|
|
573
|
+
definitionIntegrity: preset.definitionIntegrity,
|
|
574
|
+
allowedInstanceIds: Object.freeze([...seen].sort()),
|
|
575
|
+
execute: preset.execute,
|
|
576
|
+
}));
|
|
577
|
+
}
|
|
578
|
+
return defineActuarialTool({
|
|
579
|
+
id,
|
|
580
|
+
description,
|
|
581
|
+
kind: "read",
|
|
582
|
+
tenant: "required",
|
|
583
|
+
tenantKey,
|
|
584
|
+
inputSchema: diagnosticAgentToolInputSchema,
|
|
585
|
+
outputSchema: diagnosticAgentToolResultSchema,
|
|
586
|
+
execute: async (raw, tenant) => {
|
|
587
|
+
const preset = catalog.get(raw.runPresetId);
|
|
588
|
+
if (!preset)
|
|
589
|
+
throw new AgentsError("UNKNOWN_DIAGNOSTIC_PRESET", `Unknown diagnostic preset ${raw.runPresetId}`);
|
|
590
|
+
const selected = sortUniqueRequested(raw.instanceIds);
|
|
591
|
+
if (selected.some((item) => !preset.allowedInstanceIds.includes(item)))
|
|
592
|
+
throw new AgentsError("UNAPPROVED_DIAGNOSTIC_INSTANCE", "One or more diagnostic instances are not approved by the selected preset");
|
|
593
|
+
const provenance = await preset.execute({
|
|
594
|
+
tenantId: tenant,
|
|
595
|
+
instanceIds: selected,
|
|
596
|
+
});
|
|
597
|
+
try {
|
|
598
|
+
assertVerifiedDiagnosticRunProvenance(provenance);
|
|
599
|
+
}
|
|
600
|
+
catch {
|
|
601
|
+
throw new AgentsError("DIAGNOSTIC_RUN_MISMATCH", "Preset executor returned unauthenticated diagnostic provenance");
|
|
602
|
+
}
|
|
603
|
+
const filter = provenance.manifest.filter;
|
|
604
|
+
if (provenance.definition.identities.definition !==
|
|
605
|
+
definition.definitionIntegrity ||
|
|
606
|
+
provenance.manifest.runPresetId !== raw.runPresetId ||
|
|
607
|
+
!filter ||
|
|
608
|
+
JSON.stringify(filter.instanceIds ?? []) !== JSON.stringify(selected))
|
|
609
|
+
throw new AgentsError("DIAGNOSTIC_RUN_MISMATCH", "Verified run does not match the selected definition, preset, and exact instance set");
|
|
610
|
+
const instances = definition.definition.instances.filter((item) => selected.includes(item.id));
|
|
611
|
+
const formulaIds = [
|
|
612
|
+
...new Set(instances.map((item) => item.formulaId)),
|
|
613
|
+
].sort();
|
|
614
|
+
const formulaFingerprints = Object.fromEntries(formulaIds.map((formulaId) => [
|
|
615
|
+
formulaId,
|
|
616
|
+
provenance.definition.identities.formulaById[formulaId],
|
|
617
|
+
]));
|
|
618
|
+
const calculationFingerprints = Object.fromEntries(selected.map((instanceId) => [
|
|
619
|
+
instanceId,
|
|
620
|
+
provenance.definition.identities.calculationByInstanceId[instanceId],
|
|
621
|
+
]));
|
|
622
|
+
const displayPoints = (points) => points.map(({ components: _components, ...point }) => point);
|
|
623
|
+
const display = raw.view === "emergence"
|
|
624
|
+
? {
|
|
625
|
+
view: "emergence",
|
|
626
|
+
points: displayPoints(provenance.result.emergence),
|
|
627
|
+
}
|
|
628
|
+
: raw.view === "triangles"
|
|
629
|
+
? {
|
|
630
|
+
view: "triangles",
|
|
631
|
+
triangles: provenance.result.triangles,
|
|
632
|
+
}
|
|
633
|
+
: {
|
|
634
|
+
view: "latest-diagonal",
|
|
635
|
+
points: displayPoints(provenance.result.latestDiagonal),
|
|
636
|
+
};
|
|
637
|
+
return {
|
|
638
|
+
success: true,
|
|
639
|
+
data: {
|
|
640
|
+
runPresetId: raw.runPresetId,
|
|
641
|
+
instanceIds: selected,
|
|
642
|
+
definitionIntegrity: provenance.definition.identities.definition,
|
|
643
|
+
formulaFingerprints,
|
|
644
|
+
calculationFingerprints,
|
|
645
|
+
runFingerprint: provenance.runFingerprint,
|
|
646
|
+
resultFingerprint: provenance.resultFingerprint,
|
|
647
|
+
runResultFingerprint: provenance.runResultFingerprint,
|
|
648
|
+
review: provenance.review,
|
|
649
|
+
display,
|
|
650
|
+
},
|
|
651
|
+
};
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
//# sourceMappingURL=diagnostics.js.map
|