@actuarial-ts/agents 0.1.0 → 0.2.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.
@@ -0,0 +1,409 @@
1
+ /**
2
+ * Divergence explainer (interchange spec rev 2.1, Section 9 item 3): the
3
+ * agent invoked ONLY when the deterministic referee returns verdict
4
+ * "disagree". It never re-judges the comparison - the referee's verdict is
5
+ * final - it produces a structured HYPOTHESIS about why two engines diverged
6
+ * ("engine b requested sigma_interpolation=log-linear; the mack1993-vw
7
+ * profile requires mack; expected signature: SE-concentrated deviations -
8
+ * observed"), for the reviewing actuary to act on.
9
+ *
10
+ * Architecture decisions (each is load-bearing):
11
+ *
12
+ * - EVIDENCE ASSEMBLY IS PURE AND DETERMINISTIC. assembleDivergenceEvidence
13
+ * is a pure function of (CrosscheckReportDoc, MethodResultDoc a,
14
+ * MethodResultDoc b) plus the interchange profile registry - no clock, no
15
+ * randomness, no I/O. The convention map travels AS DATA: the alignment
16
+ * requirements are imported from @actuarial-ts/interchange's
17
+ * CONVENTION_PROFILES (the executable form of docs/interop/
18
+ * convention-map.md), never re-read from a file. Identical inputs yield
19
+ * identical evidence and an identical prompt, so the fixture tests can
20
+ * assert exactly what any model would be shown.
21
+ *
22
+ * - ONLY-ON-DISAGREE IS STRUCTURAL. A report whose verdict is not
23
+ * "disagree" throws AgentsError("VERDICT_NOT_DISAGREE") at assembly time;
24
+ * there is no flag to loosen. Agreement needs no explaining, and running
25
+ * an explainer on an agree/verified-by-value report would manufacture
26
+ * doubt about a comparison the referee already settled.
27
+ *
28
+ * - VIOLATIONS SURFACE FIRST. The requirement-by-requirement alignment
29
+ * check orders findings violated > unverifiable > satisfied, so the most
30
+ * probable root cause (a profile requirement the engine visibly did not
31
+ * run) is the first thing both the model and the human read.
32
+ *
33
+ * - READ-ONLY BY CONSTRUCTION. The explainer gets exactly one tool, and it
34
+ * only returns the already-assembled evidence (carried on the
35
+ * RequestContext under DIVERGENCE_EVIDENCE_CONTEXT_KEY); there is no
36
+ * action tool to reach for. The prompt also embeds the full evidence, so
37
+ * a single generate call suffices and the tool exists for follow-up
38
+ * turns, not as a required hop.
39
+ *
40
+ * HOUSE GOTCHA honored: no literal backtick characters in instruction
41
+ * content (a backtick inside a template literal once broke server boot).
42
+ */
43
+ import { Agent } from "@mastra/core/agent";
44
+ import { RequestContext } from "@mastra/core/request-context";
45
+ import { ReservingError } from "@actuarial-ts/core";
46
+ import { CONVENTION_PROFILES, crosscheckReportDocSchema, methodResultDocSchema, } from "@actuarial-ts/interchange";
47
+ import { z } from "zod";
48
+ import { AgentsError } from "./errors.js";
49
+ import { defineActuarialTool, toolRegistry } from "./tools.js";
50
+ // ---------------------------------------------------------------------------
51
+ // Evidence assembly (pure)
52
+ function stableJson(value) {
53
+ return value === undefined ? "(absent)" : JSON.stringify(value);
54
+ }
55
+ function sameValue(x, y) {
56
+ return x === y || JSON.stringify(x) === JSON.stringify(y);
57
+ }
58
+ function validateDoc(label, doc, schema) {
59
+ const parsed = schema.safeParse(doc);
60
+ if (!parsed.success) {
61
+ throw new ReservingError("BAD_INTERCHANGE", `assembleDivergenceEvidence input "${label}" is malformed: ${parsed
62
+ .error.issues.map((i) => `${i.path.join(".") || "$"}: ${i.message}`)
63
+ .join("; ")}`);
64
+ }
65
+ return parsed.data;
66
+ }
67
+ function engineMatches(doc, stamp) {
68
+ return doc.result.engine.name === stamp.name && doc.result.engine.version === stamp.version;
69
+ }
70
+ const STATUS_RANK = {
71
+ violated: 0,
72
+ unverifiable: 1,
73
+ satisfied: 2,
74
+ };
75
+ function alignmentFindingsFor(side, doc, profile, claimedProfileId) {
76
+ const engineName = doc.result.engine.name;
77
+ if (profile === null) {
78
+ return [
79
+ {
80
+ engine: side,
81
+ engineName,
82
+ parameter: "*",
83
+ required: undefined,
84
+ requested: undefined,
85
+ effective: undefined,
86
+ status: "unverifiable",
87
+ detail: claimedProfileId === null
88
+ ? `engine ${side} (${engineName}): no convention profile is claimed on either result, so ` +
89
+ "no alignment requirements exist to check against"
90
+ : `engine ${side} (${engineName}): claimed profile "${claimedProfileId}" is not in the ` +
91
+ "interchange profile registry; its requirements cannot be checked",
92
+ },
93
+ ];
94
+ }
95
+ const alignment = profile.alignment[engineName] ?? null;
96
+ if (alignment === null) {
97
+ return [
98
+ {
99
+ engine: side,
100
+ engineName,
101
+ parameter: "*",
102
+ required: undefined,
103
+ requested: undefined,
104
+ effective: undefined,
105
+ status: "unverifiable",
106
+ detail: `engine ${side} (${engineName}): profile "${profile.id}" has no alignment entry for ` +
107
+ "this engine name; its requirements cannot be checked",
108
+ },
109
+ ];
110
+ }
111
+ const requestedParams = doc.result.parameters;
112
+ const effectiveParams = doc.result.effectiveParameters;
113
+ const findings = [];
114
+ for (const [parameter, required] of Object.entries(alignment.parameters)) {
115
+ const requested = requestedParams[parameter];
116
+ const effective = effectiveParams?.[parameter];
117
+ const ran = effective !== undefined ? effective : requested;
118
+ const base = {
119
+ engine: side,
120
+ engineName,
121
+ parameter,
122
+ required,
123
+ requested,
124
+ effective,
125
+ };
126
+ if (ran === undefined) {
127
+ findings.push({
128
+ ...base,
129
+ status: "unverifiable",
130
+ detail: `engine ${side} (${engineName}) parameter "${parameter}": profile "${profile.id}" requires ` +
131
+ `${stableJson(required)}, but the result records no such parameter (a prose requirement or ` +
132
+ "an unrecorded setting); not mechanically checkable",
133
+ });
134
+ }
135
+ else if (sameValue(required, ran)) {
136
+ findings.push({
137
+ ...base,
138
+ status: "satisfied",
139
+ detail: `engine ${side} (${engineName}) parameter "${parameter}": profile "${profile.id}" requires ` +
140
+ `${stableJson(required)}; the engine ran ${stableJson(ran)}`,
141
+ });
142
+ }
143
+ else {
144
+ const deviationNote = effective !== undefined && !sameValue(effective, requested)
145
+ ? ` (requested ${stableJson(requested)}, effective ${stableJson(effective)})`
146
+ : "";
147
+ findings.push({
148
+ ...base,
149
+ status: "violated",
150
+ detail: `VIOLATED: profile "${profile.id}" requires ${parameter}=${stableJson(required)} for ` +
151
+ `${engineName}; engine ${side} ran ${parameter}=${stableJson(ran)}${deviationNote}`,
152
+ });
153
+ }
154
+ }
155
+ return findings;
156
+ }
157
+ function deviationSignatureOf(report) {
158
+ const body = report.report;
159
+ const tolerance = {
160
+ central: body.tolerance.central,
161
+ standardError: body.tolerance.standardError,
162
+ };
163
+ let maxCentral = 0;
164
+ let maxSe = null;
165
+ const ranked = [];
166
+ for (const row of body.deviations.perOrigin) {
167
+ for (const metric of ["ultimate", "unpaid"]) {
168
+ const deviation = row[metric];
169
+ if (deviation === null)
170
+ continue;
171
+ maxCentral = Math.max(maxCentral, deviation);
172
+ ranked.push({ origin: row.origin, metric, deviation });
173
+ }
174
+ if (row.standardError !== null) {
175
+ maxSe = Math.max(maxSe ?? 0, row.standardError);
176
+ ranked.push({ origin: row.origin, metric: "standardError", deviation: row.standardError });
177
+ }
178
+ }
179
+ const totals = body.deviations.totals;
180
+ for (const metric of ["ultimate", "unpaid"]) {
181
+ const deviation = totals[metric];
182
+ if (deviation !== null)
183
+ maxCentral = Math.max(maxCentral, deviation);
184
+ }
185
+ if (totals.standardError !== null)
186
+ maxSe = Math.max(maxSe ?? 0, totals.standardError);
187
+ const centralExceeds = maxCentral > tolerance.central;
188
+ const seExceeds = tolerance.standardError !== null && maxSe !== null && maxSe > tolerance.standardError;
189
+ const concentration = centralExceeds && seExceeds
190
+ ? "mixed"
191
+ : centralExceeds
192
+ ? "central"
193
+ : seExceeds
194
+ ? "standard-error"
195
+ : "none";
196
+ ranked.sort((x, y) => y.deviation - x.deviation);
197
+ return {
198
+ tolerance,
199
+ maxCentral,
200
+ maxStandardError: maxSe,
201
+ centralExceedsTolerance: centralExceeds,
202
+ standardErrorExceedsTolerance: seExceeds,
203
+ concentration,
204
+ totals: {
205
+ ultimate: totals.ultimate,
206
+ unpaid: totals.unpaid,
207
+ standardError: totals.standardError,
208
+ },
209
+ worstOrigins: ranked.slice(0, 5),
210
+ };
211
+ }
212
+ /**
213
+ * Assembles the divergence evidence for a disagree crosscheck: pure and
214
+ * deterministic (see the module doc). Throws:
215
+ * - AgentsError("VERDICT_NOT_DISAGREE") when the report's verdict is not
216
+ * "disagree" - the only-on-disagree rule is structural, not advisory;
217
+ * - AgentsError("DIVERGENCE_INPUT_MISMATCH") when the supplied result docs
218
+ * do not match the report's engine stamps (wrong docs, or a/b swapped);
219
+ * - ReservingError("BAD_INTERCHANGE") when any input document is malformed.
220
+ */
221
+ export function assembleDivergenceEvidence(options) {
222
+ const report = validateDoc("report", options.report, crosscheckReportDocSchema);
223
+ const a = validateDoc("a", options.a, methodResultDocSchema);
224
+ const b = validateDoc("b", options.b, methodResultDocSchema);
225
+ const body = report.report;
226
+ if (body.verdict !== "disagree") {
227
+ throw new AgentsError("VERDICT_NOT_DISAGREE", `The divergence explainer is invoked ONLY on a "disagree" crosscheck verdict (spec 9 item 3); ` +
228
+ `this report's verdict is "${body.verdict}" - there is no divergence to explain`);
229
+ }
230
+ if (!engineMatches(a, body.engines.a) || !engineMatches(b, body.engines.b)) {
231
+ const swapped = engineMatches(a, body.engines.b) && engineMatches(b, body.engines.a);
232
+ throw new AgentsError("DIVERGENCE_INPUT_MISMATCH", swapped
233
+ ? "The supplied result docs are SWAPPED relative to the report: doc a matches the report's " +
234
+ "engine b and vice versa; pass them in the report's a/b order"
235
+ : `The supplied result docs do not match the report's engine stamps: report compared ` +
236
+ `a=${body.engines.a.name}@${body.engines.a.version} vs ` +
237
+ `b=${body.engines.b.name}@${body.engines.b.version}, got ` +
238
+ `a=${a.result.engine.name}@${a.result.engine.version} and ` +
239
+ `b=${b.result.engine.name}@${b.result.engine.version}`);
240
+ }
241
+ const claimedProfileId = a.result.engine.conventionProfile ?? b.result.engine.conventionProfile ?? null;
242
+ const profile = claimedProfileId !== null ? (CONVENTION_PROFILES[claimedProfileId] ?? null) : null;
243
+ const engineEvidenceOf = (doc) => ({
244
+ name: doc.result.engine.name,
245
+ version: doc.result.engine.version,
246
+ conventionProfile: doc.result.engine.conventionProfile ?? null,
247
+ method: doc.result.method,
248
+ requested: doc.result.parameters,
249
+ effective: doc.result.effectiveParameters ?? null,
250
+ profileAlignment: profile === null
251
+ ? null
252
+ : (profile.alignment[doc.result.engine.name] ?? null),
253
+ });
254
+ const findings = [
255
+ ...alignmentFindingsFor("a", a, profile, claimedProfileId),
256
+ ...alignmentFindingsFor("b", b, profile, claimedProfileId),
257
+ ].sort((x, y) => STATUS_RANK[x.status] - STATUS_RANK[y.status]);
258
+ return {
259
+ verdict: "disagree",
260
+ profile: {
261
+ id: claimedProfileId,
262
+ known: profile !== null,
263
+ description: profile?.description ?? null,
264
+ tolerance: profile !== null ? { ...profile.tolerance } : null,
265
+ },
266
+ alignmentFindings: findings,
267
+ engines: { a: engineEvidenceOf(a), b: engineEvidenceOf(b) },
268
+ deviationSignature: deviationSignatureOf(report),
269
+ warnings: {
270
+ report: [...body.warnings],
271
+ engineA: [...(a.result.warnings ?? [])],
272
+ engineB: [...(b.result.warnings ?? [])],
273
+ },
274
+ };
275
+ }
276
+ // ---------------------------------------------------------------------------
277
+ // Structured hypothesis
278
+ /** The explainer's structured output (spec 9 item 3). */
279
+ export const divergenceHypothesisSchema = z.object({
280
+ /** The single most probable root cause, stated as a testable claim. */
281
+ suspectedCause: z.string().min(1),
282
+ /** The exact misaligned parameter/flag name (e.g. "sigma_interpolation"),
283
+ * or null when no specific flag is implicated. */
284
+ misalignedFlag: z.string().min(1).nullable(),
285
+ /** The deviation signature the suspected cause WOULD produce. */
286
+ expectedSignature: z.string().min(1),
287
+ /** The deviation signature the evidence actually shows. */
288
+ observedSignature: z.string().min(1),
289
+ /** What the operator should do next to confirm or fix. */
290
+ recommendation: z.string().min(1),
291
+ });
292
+ // ---------------------------------------------------------------------------
293
+ // Instructions + prompt assembly (pure, deterministic)
294
+ /** RequestContext key the evidence tool reads (set by explainDivergence). */
295
+ export const DIVERGENCE_EVIDENCE_CONTEXT_KEY = "divergenceEvidence";
296
+ /**
297
+ * The explainer's instruction template. A constant, not a builder: the
298
+ * explainer has exactly one job and no host-specific domain sections. No
299
+ * backtick characters (house gotcha).
300
+ */
301
+ export const DIVERGENCE_EXPLAINER_INSTRUCTIONS = [
302
+ "You are a cross-engine divergence diagnostician inside an actuarial reserving toolchain. A deterministic referee compared the same computation run by two independent engines and returned the verdict \"disagree\". Your job is to produce a structured HYPOTHESIS about the root cause - you never re-litigate the verdict, and you never change any state.",
303
+ "## Working rules",
304
+ [
305
+ "1. Every claim you make must come from the supplied divergence evidence (in the user message, and available again via the get_divergence_evidence tool). Never invent parameters, deviations, or profile requirements.",
306
+ "2. The alignment findings are ordered violations first. A VIOLATED finding - a convention-profile requirement the engine visibly did not run - is the strongest root-cause candidate; check whether its expected deviation signature matches the observed one before settling on it.",
307
+ "3. The deviation signature tells you WHERE the disagreement lives: central estimates (ultimates/unpaid), standard errors, or both. A sigma/variance-convention misalignment concentrates in standard errors while central estimates agree; a factor/selection misalignment moves central estimates.",
308
+ "4. In misalignedFlag, name the exact parameter as it appears in the evidence (for example sigma_interpolation), or use null when no specific flag is implicated.",
309
+ "5. Be direct and technical; the reader is a credentialed actuary. State the hypothesis, the expected vs observed signature, and one concrete next step.",
310
+ ].join("\n"),
311
+ ].join("\n\n");
312
+ /**
313
+ * Deterministic user-prompt assembly: a readable summary (violations first,
314
+ * then the deviation signature) followed by the full evidence as JSON.
315
+ * Identical evidence yields a byte-identical prompt, so tests can pin
316
+ * exactly what any model is shown.
317
+ */
318
+ export function assembleDivergencePrompt(evidence) {
319
+ const sig = evidence.deviationSignature;
320
+ const profileLine = evidence.profile.id === null
321
+ ? "Convention profile: none claimed."
322
+ : `Convention profile: "${evidence.profile.id}"${evidence.profile.known ? "" : " (NOT in the registry)"} - ${evidence.profile.description ?? "no description"}`;
323
+ const findingLines = evidence.alignmentFindings.map((f) => `- [${f.status.toUpperCase()}] ${f.detail}`);
324
+ const seLine = sig.maxStandardError === null
325
+ ? "standard errors: not compared"
326
+ : `max standard-error deviation ${sig.maxStandardError} (tolerance ${sig.tolerance.standardError ?? "out of scope"}; ${sig.standardErrorExceedsTolerance ? "EXCEEDED" : "within"})`;
327
+ const sections = [
328
+ "A crosscheck referee compared two engines running the same computation and returned verdict DISAGREE.",
329
+ `Engine a: ${evidence.engines.a.name}@${evidence.engines.a.version} (method ${evidence.engines.a.method}). ` +
330
+ `Engine b: ${evidence.engines.b.name}@${evidence.engines.b.version} (method ${evidence.engines.b.method}).`,
331
+ profileLine,
332
+ "Alignment findings (violations first):\n" + findingLines.join("\n"),
333
+ `Deviation signature: concentration ${sig.concentration}; max central deviation ${sig.maxCentral} ` +
334
+ `(tolerance ${sig.tolerance.central}; ${sig.centralExceedsTolerance ? "EXCEEDED" : "within"}); ${seLine}.`,
335
+ "Full assembled evidence (JSON):\n" + JSON.stringify(evidence, null, 2),
336
+ "Produce the structured hypothesis: suspectedCause, misalignedFlag (the exact parameter name, or null), expectedSignature, observedSignature, recommendation.",
337
+ ];
338
+ return sections.join("\n\n");
339
+ }
340
+ // ---------------------------------------------------------------------------
341
+ // The read-only evidence tool
342
+ /**
343
+ * The explainer's single tool: returns the already-assembled evidence from
344
+ * the request context. Read-only by construction - it can only restate what
345
+ * explainDivergence assembled; there is nothing to mutate.
346
+ */
347
+ export function createDivergenceEvidenceTool() {
348
+ return defineActuarialTool({
349
+ id: "get_divergence_evidence",
350
+ description: "Returns the assembled divergence evidence for the disagree crosscheck under review: " +
351
+ "convention-profile alignment requirements, each engine's requested vs effective parameters, " +
352
+ "requirement-by-requirement findings (violations first), the deviation signature, and all " +
353
+ "warnings. Read-only.",
354
+ kind: "read",
355
+ inputSchema: z.object({}),
356
+ execute: async (_input, context) => {
357
+ const evidence = context.requestContext?.get(DIVERGENCE_EVIDENCE_CONTEXT_KEY);
358
+ if (evidence === undefined) {
359
+ throw new AgentsError("NO_DIVERGENCE_EVIDENCE", `No assembled divergence evidence in the request context (key "${DIVERGENCE_EVIDENCE_CONTEXT_KEY}"); ` +
360
+ "drive this agent through explainDivergence, which assembles and injects it");
361
+ }
362
+ return { success: true, evidence: evidence };
363
+ },
364
+ });
365
+ }
366
+ /**
367
+ * Builds the divergence-explainer Agent: the constant instruction template
368
+ * plus the single read-only evidence tool. Drive it with explainDivergence,
369
+ * which assembles the evidence, injects it into the request context, and
370
+ * runs the one structured-output generate call.
371
+ */
372
+ export function createDivergenceExplainer(options) {
373
+ return new Agent({
374
+ id: options.id ?? "divergence-explainer",
375
+ name: options.name ?? "Divergence Explainer",
376
+ description: options.description ??
377
+ "Cross-engine divergence diagnostician: on a disagree crosscheck verdict, reads the assembled " +
378
+ "evidence (profile requirements, requested vs effective parameters, deviation signature) and " +
379
+ "produces a structured root-cause hypothesis. Read-only; never re-judges the referee.",
380
+ instructions: DIVERGENCE_EXPLAINER_INSTRUCTIONS,
381
+ model: options.model,
382
+ tools: toolRegistry([createDivergenceEvidenceTool()]).tools,
383
+ });
384
+ }
385
+ /**
386
+ * Drives one structured-output generate call: assembles the evidence
387
+ * (throwing on a non-disagree verdict), injects it into the request context
388
+ * for the evidence tool, prompts the explainer, and zod-validates the
389
+ * model's hypothesis before returning it - the boundary is validated in
390
+ * both directions.
391
+ */
392
+ export async function explainDivergence(options) {
393
+ const evidence = assembleDivergenceEvidence({
394
+ report: options.report,
395
+ a: options.a,
396
+ b: options.b,
397
+ });
398
+ const requestContext = options.requestContext ?? new RequestContext();
399
+ requestContext.set(DIVERGENCE_EVIDENCE_CONTEXT_KEY, evidence);
400
+ const prompt = assembleDivergencePrompt(evidence);
401
+ const result = await options.explainer.generate([{ role: "user", content: prompt }], {
402
+ structuredOutput: { schema: divergenceHypothesisSchema },
403
+ requestContext,
404
+ maxSteps: options.maxSteps ?? 4,
405
+ });
406
+ const hypothesis = divergenceHypothesisSchema.parse(result.object);
407
+ return { hypothesis, evidence, prompt };
408
+ }
409
+ //# sourceMappingURL=divergence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"divergence.js","sourceRoot":"","sources":["../src/divergence.ts"],"names":[],"mappings":"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"}
package/dist/errors.d.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  * thrown during tool execution into a { success: false, error } envelope.
11
11
  */
12
12
  /** Every machine-readable code an AgentsError can carry. */
13
- export declare const AGENTS_ERROR_CODES: readonly ["NO_TENANT_CONTEXT", "TENANT_IN_SCHEMA", "BAD_INPUT_SCHEMA", "BAD_GATE", "MISSING_RATIONALE", "DUPLICATE_TOOL_ID"];
13
+ export declare const AGENTS_ERROR_CODES: readonly ["NO_TENANT_CONTEXT", "TENANT_IN_SCHEMA", "BAD_INPUT_SCHEMA", "BAD_GATE", "MISSING_RATIONALE", "DUPLICATE_TOOL_ID", "BAD_PROMOTION_OPTIONS", "EMPTY_STUDY", "TOLERANCE_CEILING_EXCEEDED", "SEGMENT_UNRESOLVED", "SEGMENT_AMBIGUOUS", "VERDICT_NOT_DISAGREE", "DIVERGENCE_INPUT_MISMATCH", "NO_DIVERGENCE_EVIDENCE", "REMOTE_RESULT_INVALID", "MCP_SELF_TEST_FAILED"];
14
14
  export type AgentsErrorCode = (typeof AGENTS_ERROR_CODES)[number];
15
15
  /**
16
16
  * Thrown for invalid agent-toolkit input: tenant-seam violations, malformed
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,8HAYrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;gBACnB,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM;CAKnD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,+WAgCrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;gBACnB,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM;CAKnD"}
package/dist/errors.js CHANGED
@@ -22,6 +22,26 @@ export const AGENTS_ERROR_CODES = [
22
22
  "MISSING_RATIONALE",
23
23
  /** Two tools with the same id were passed to toolRegistry. */
24
24
  "DUPLICATE_TOOL_ID",
25
+ /** promoteStudy was called with malformed deps/options (programmer error). */
26
+ "BAD_PROMOTION_OPTIONS",
27
+ /** A study document carries no selections; nothing to promote. */
28
+ "EMPTY_STUDY",
29
+ /** The study's stated replayTolerance exceeds the host ceiling (spec 6 Gate 1). */
30
+ "TOLERANCE_CEILING_EXCEEDED",
31
+ /** A selection's segment labels match no host workspace target (no fuzzy matching in v1). */
32
+ "SEGMENT_UNRESOLVED",
33
+ /** Two selections resolve to the same workspace target; v1 promotes one selection per segment. */
34
+ "SEGMENT_AMBIGUOUS",
35
+ /** The divergence explainer was invoked on a report whose verdict is not "disagree" (spec 9 item 3: only-on-disagree is structural). */
36
+ "VERDICT_NOT_DISAGREE",
37
+ /** The result docs handed to the divergence explainer do not match the crosscheck report's engine stamps (wrong docs, or a/b swapped). */
38
+ "DIVERGENCE_INPUT_MISMATCH",
39
+ /** The divergence evidence tool ran without assembled evidence in the request context (drive the agent through explainDivergence). */
40
+ "NO_DIVERGENCE_EVIDENCE",
41
+ /** A remote sidecar 2xx response failed interchange parseDocument (bad JSON, bad schema, broken integrity tag, or a non-result kind). */
42
+ "REMOTE_RESULT_INVALID",
43
+ /** The boot self-test found an MCP-exposed probe tool that did NOT fail closed without tenant context; the MCP tenant seam is not wired up and the server must abort startup. */
44
+ "MCP_SELF_TEST_FAILED",
25
45
  ];
26
46
  /**
27
47
  * Thrown for invalid agent-toolkit input: tenant-seam violations, malformed
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,sFAAsF;IACtF,mBAAmB;IACnB,sHAAsH;IACtH,kBAAkB;IAClB,kBAAkB;IAClB,2EAA2E;IAC3E,UAAU;IACV,iEAAiE;IACjE,mBAAmB;IACnB,8DAA8D;IAC9D,mBAAmB;CACX,CAAC;AAIX;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,IAAI,CAAkB;IAC/B,YAAY,IAAqB,EAAE,OAAe;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,sFAAsF;IACtF,mBAAmB;IACnB,sHAAsH;IACtH,kBAAkB;IAClB,kBAAkB;IAClB,2EAA2E;IAC3E,UAAU;IACV,iEAAiE;IACjE,mBAAmB;IACnB,8DAA8D;IAC9D,mBAAmB;IACnB,8EAA8E;IAC9E,uBAAuB;IACvB,kEAAkE;IAClE,aAAa;IACb,mFAAmF;IACnF,4BAA4B;IAC5B,6FAA6F;IAC7F,oBAAoB;IACpB,kGAAkG;IAClG,mBAAmB;IACnB,wIAAwI;IACxI,sBAAsB;IACtB,0IAA0I;IAC1I,2BAA2B;IAC3B,sIAAsI;IACtI,wBAAwB;IACxB,yIAAyI;IACzI,uBAAuB;IACvB,iLAAiL;IACjL,sBAAsB;CACd,CAAC;AAIX;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,IAAI,CAAkB;IAC/B,YAAY,IAAqB,EAAE,OAAe;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  export * from "./errors.js";
2
2
  export * from "./tools.js";
3
3
  export * from "./judgment.js";
4
+ export * from "./promotion.js";
4
5
  export * from "./advisor.js";
5
6
  export * from "./evals.js";
7
+ export * from "./divergence.js";
8
+ export * from "./remote.js";
9
+ export * from "./mcp.js";
6
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,10 @@
1
1
  export * from "./errors.js";
2
2
  export * from "./tools.js";
3
3
  export * from "./judgment.js";
4
+ export * from "./promotion.js";
4
5
  export * from "./advisor.js";
5
6
  export * from "./evals.js";
7
+ export * from "./divergence.js";
8
+ export * from "./remote.js";
9
+ export * from "./mcp.js";
6
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,130 @@
1
+ /**
2
+ * MCP tenant seam + boot self-test for the governed workspace.
3
+ *
4
+ * When the workspace is exposed over the Model Context Protocol, external AI
5
+ * clients read everything and mutate nothing directly. The one hard guarantee
6
+ * is that EVERY exposed tool resolves its tenant (project id) from the MCP
7
+ * request's auth info, never from the model — the same secureToolWrapper rule
8
+ * the ActNG server proved in production, restated for the MCP transport.
9
+ *
10
+ * @mastra/mcp gives no built-in per-tool authorization outside its EE FGA path,
11
+ * so a missed wire-up FAILS OPEN: a tool that forgets to read authInfo would
12
+ * happily serve an unauthenticated caller. These two helpers close that caveat:
13
+ *
14
+ * 1. requireMcpTenant — the read side. A tool calls it instead of trusting the
15
+ * model; absent auth info it THROWS AgentsError("NO_TENANT_CONTEXT"), which
16
+ * the defineActuarialTool wrapper turns into a { success:false } envelope.
17
+ * A tool built on it fails CLOSED.
18
+ *
19
+ * 2. assertFailClosed — the proof. At server startup, drive a probe read tool
20
+ * through the server WITHOUT auth and assert it fails closed. If the probe
21
+ * SUCCEEDS, the seam is not wired up: this throws MCP_SELF_TEST_FAILED and
22
+ * startup MUST abort.
23
+ *
24
+ * ---------------------------------------------------------------------------
25
+ * VERIFIED against the installed @mastra/mcp 1.14.0 (house rule — types and
26
+ * compiled source, not memory):
27
+ *
28
+ * - MCPServer.executeTool(toolId, args, executionContext?: { messages?,
29
+ * toolCallId?, requestContext? }): Promise<any> returns the tool's execute
30
+ * result VERBATIM (dist/index.js: `const result = await tool.execute(...);
31
+ * return result;`). For a defineActuarialTool with no outputSchema the core
32
+ * tool builder passes the value through untouched, so an executeTool caller
33
+ * sees exactly the { success:false, error:{ code } } envelope the wrapper
34
+ * produced. Argument validation runs FIRST and, on failure, short-circuits
35
+ * to a { error:true, message } object before the tool ever executes — hence
36
+ * assertFailClosed passes minimal VALID probe args.
37
+ *
38
+ * - Auth-context access path. On the real streamable-HTTP call path the SDK
39
+ * copies the transport `extra` (with `authInfo` from `req.auth`) into the
40
+ * tool context TWO ways: directly at `context.mcp.extra`, and — via
41
+ * createProxiedRequestContext — as INDIVIDUAL keys set on a fresh
42
+ * RequestContext (`context.requestContext.get("authInfo")`). NOTE the
43
+ * surprise: the installed 1.14.0 sets each extra key on the RequestContext
44
+ * verbatim, so the tenant lives at `requestContext.get("authInfo")`, NOT
45
+ * under a single `"mcp.extra"` key as the research draft documented. This
46
+ * helper tries all three shapes so it is correct against both the installed
47
+ * package and the documented pattern.
48
+ */
49
+ import type { ActuarialToolContext } from "./tools.js";
50
+ import { type AgentsErrorCode } from "./errors.js";
51
+ /**
52
+ * The MCP auth-info bag: whatever the host's bearer-token middleware set on
53
+ * `req.auth` before delegating to startHTTP (e.g. `{ projectId }`). Values are
54
+ * unknown — requireMcpTenant proves the tenant is a non-empty string.
55
+ */
56
+ export interface McpAuthInfo {
57
+ [key: string]: unknown;
58
+ }
59
+ /**
60
+ * The transport `extra` (MCP SDK RequestHandlerExtra) surfaced to a tool at
61
+ * `context.mcp.extra`. Only `authInfo` is load-bearing here; the rest
62
+ * (sessionId, requestInfo, signal, ...) is carried opaquely.
63
+ */
64
+ export interface McpRequestExtra {
65
+ authInfo?: McpAuthInfo;
66
+ [key: string]: unknown;
67
+ }
68
+ /**
69
+ * The structural slice of a Mastra tool-execution context this seam needs on
70
+ * the MCP path: the tenant-seam `requestContext` (inherited from
71
+ * ActuarialToolContext) plus the MCP-specific `mcp.extra`. Typed structurally
72
+ * so tests exercise the helper with a plain object and no live MCP server.
73
+ */
74
+ export interface McpToolContext extends ActuarialToolContext {
75
+ mcp?: {
76
+ extra?: McpRequestExtra;
77
+ };
78
+ }
79
+ /**
80
+ * Reads the tenant id (default key "projectId") from the MCP execution
81
+ * context's auth info — the server-set identity, never the model. THROWS a
82
+ * typed AgentsError("NO_TENANT_CONTEXT") when the auth info or the key is
83
+ * absent, non-string, or empty. Inside a defineActuarialTool execute the
84
+ * wrapper converts that throw into a { success:false } envelope, so a tool
85
+ * built on requireMcpTenant fails CLOSED for any unauthenticated MCP caller.
86
+ */
87
+ export declare function requireMcpTenant(context: McpToolContext | undefined, key?: string): string;
88
+ /**
89
+ * The structural slice of @mastra/mcp's MCPServer that assertFailClosed drives.
90
+ * A real MCPServer satisfies it; so does a bare `{ executeTool }` stub, so the
91
+ * self-test is unit-testable without booting a transport. Verified against the
92
+ * installed executeTool signature (see the file header).
93
+ */
94
+ export interface McpToolServer {
95
+ executeTool(toolId: string, args: Record<string, unknown>, executionContext?: {
96
+ requestContext?: unknown;
97
+ messages?: unknown[];
98
+ toolCallId?: string;
99
+ }): Promise<unknown>;
100
+ }
101
+ export interface AssertFailClosedOptions {
102
+ /** The MCP server whose exposed tools are being wired up (typically the workspace MCPServer). */
103
+ server: McpToolServer;
104
+ /**
105
+ * A READ tool that resolves its tenant via requireMcpTenant. Driven with no
106
+ * auth info, it must fail closed with the tenant error code.
107
+ */
108
+ probeToolId: string;
109
+ /**
110
+ * Minimal VALID args for the probe tool's input schema. Defaults to `{}`
111
+ * (correct for read tools whose schema is `z.object({})` or all-optional).
112
+ * Args that fail schema validation would short-circuit before the tenant
113
+ * check runs, so pass real minimal args for probes that require input.
114
+ */
115
+ probeArgs?: Record<string, unknown>;
116
+ /** The failure code the probe must fail closed with. Defaults to NO_TENANT_CONTEXT. */
117
+ expectedErrorCode?: AgentsErrorCode;
118
+ }
119
+ /**
120
+ * The boot self-test. Drives {@link AssertFailClosedOptions.probeToolId}
121
+ * through the server WITHOUT any auth info and asserts it fails closed with the
122
+ * tenant error code. THROWS AgentsError("MCP_SELF_TEST_FAILED") loudly for any
123
+ * other outcome — most importantly if the probe SUCCEEDED, which means the tool
124
+ * did not require tenant context and the MCP tenant seam is a fail-open hole.
125
+ *
126
+ * Call this at server startup whenever MCP is enabled, and ABORT startup if it
127
+ * throws: a governed workspace must never accept unauthenticated MCP clients.
128
+ */
129
+ export declare function assertFailClosed(options: AssertFailClosedOptions): Promise<void>;
130
+ //# sourceMappingURL=mcp.d.ts.map