@kindgi/guardrails 0.0.0-bootstrap.0 → 0.1.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/LICENSE +201 -0
- package/README.md +78 -1
- package/dist/action-handler.d.ts +82 -0
- package/dist/action-handler.d.ts.map +1 -0
- package/dist/action-handler.js +120 -0
- package/dist/action-handler.js.map +1 -0
- package/dist/checks.d.ts +9 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +235 -0
- package/dist/checks.js.map +1 -0
- package/dist/define-check.d.ts +93 -0
- package/dist/define-check.d.ts.map +1 -0
- package/dist/define-check.js +110 -0
- package/dist/define-check.js.map +1 -0
- package/dist/define.d.ts +27 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +126 -0
- package/dist/define.js.map +1 -0
- package/dist/engine.d.ts +49 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +198 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.d.ts +91 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -0
- package/dist/execution-strategy.d.ts +80 -0
- package/dist/execution-strategy.d.ts.map +1 -0
- package/dist/execution-strategy.js +96 -0
- package/dist/execution-strategy.js.map +1 -0
- package/dist/guardrail.schema.json +261 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/judge.d.ts +31 -0
- package/dist/judge.d.ts.map +1 -0
- package/dist/judge.js +171 -0
- package/dist/judge.js.map +1 -0
- package/dist/types.d.ts +407 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -4
- package/src/action-handler.ts +179 -0
- package/src/checks.ts +236 -0
- package/src/define-check.ts +207 -0
- package/src/define.ts +146 -0
- package/src/engine.ts +271 -0
- package/src/errors.ts +107 -0
- package/src/execution-strategy.ts +184 -0
- package/src/guardrail.schema.json +261 -0
- package/src/index.ts +79 -0
- package/src/judge.ts +221 -0
- package/src/types.ts +455 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (C) 2026 Kindgi Inc.
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
Capability,
|
|
6
|
+
ModelProvider,
|
|
7
|
+
ProviderRegistry,
|
|
8
|
+
TenantPolicy,
|
|
9
|
+
} from '@kindgi/capabilities';
|
|
10
|
+
import type { ComplianceProvider } from '@kindgi/compliance';
|
|
11
|
+
import type {
|
|
12
|
+
AgentId,
|
|
13
|
+
FlowId,
|
|
14
|
+
GuardrailId,
|
|
15
|
+
ProjectId,
|
|
16
|
+
RunId,
|
|
17
|
+
TenantId,
|
|
18
|
+
Timestamp,
|
|
19
|
+
ToolId,
|
|
20
|
+
} from '@kindgi/types';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* How a guardrail is checked. Open string — the engine dispatches
|
|
24
|
+
* on this value through an `ExecutionStrategyRegistry`. Built-in kinds
|
|
25
|
+
* are `'zero-llm' | 'llm-judge' | 'external'` (see
|
|
26
|
+
* `execution-strategy.ts`). Adapter packages register strategies for
|
|
27
|
+
* their own kinds without touching the engine — e.g. `'sandbox-code'`.
|
|
28
|
+
*
|
|
29
|
+
* The `BUILT_IN_GUARDRAIL_KINDS` constant enumerates the well-known values
|
|
30
|
+
* (the schema lists them as `examples`); the schema accepts any non-empty
|
|
31
|
+
* kind. `defineGuardrail` still requires a registered check of the same
|
|
32
|
+
* kind, and runtime dispatch uses the registered strategies, not this
|
|
33
|
+
* union.
|
|
34
|
+
*/
|
|
35
|
+
export type GuardrailKind = string;
|
|
36
|
+
|
|
37
|
+
export const BUILT_IN_GUARDRAIL_KINDS = ['zero-llm', 'llm-judge', 'external'] as const;
|
|
38
|
+
export type BuiltInGuardrailKind = (typeof BUILT_IN_GUARDRAIL_KINDS)[number];
|
|
39
|
+
|
|
40
|
+
export type GuardrailSeverity = 'info' | 'warn' | 'error' | 'critical';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Actions the engine surfaces when a check fails. Open string — the
|
|
44
|
+
* caller (e.g. the agent runtime) matches on this to decide behavior,
|
|
45
|
+
* and an optional `ActionHandlerRegistry` (see `action-handler.ts`)
|
|
46
|
+
* lets adapters register new actions like `'hitl-review'` or
|
|
47
|
+
* `'redact-then-continue'`. Any non-empty name is accepted when the
|
|
48
|
+
* guardrail is defined; with `EvaluationBindings.actions` set, a name
|
|
49
|
+
* with no registered handler fails with `unknown-action` when the
|
|
50
|
+
* guardrail fires.
|
|
51
|
+
*/
|
|
52
|
+
export type OnViolation = string;
|
|
53
|
+
|
|
54
|
+
export const BUILT_IN_ON_VIOLATIONS = [
|
|
55
|
+
'halt',
|
|
56
|
+
'retry',
|
|
57
|
+
'escalate',
|
|
58
|
+
'log-only',
|
|
59
|
+
'compensate',
|
|
60
|
+
] as const;
|
|
61
|
+
export type BuiltInOnViolation = (typeof BUILT_IN_ON_VIOLATIONS)[number];
|
|
62
|
+
|
|
63
|
+
export type ScopeWhen = 'always' | 'ci-only' | 'runtime-only';
|
|
64
|
+
|
|
65
|
+
export interface Action {
|
|
66
|
+
readonly 'on-violation': OnViolation;
|
|
67
|
+
readonly retry?: { readonly maxAttempts: number };
|
|
68
|
+
readonly escalateTo?: string;
|
|
69
|
+
readonly compensateWith?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface Scope {
|
|
73
|
+
readonly when?: ScopeWhen;
|
|
74
|
+
readonly agents?: readonly AgentId[];
|
|
75
|
+
readonly flows?: readonly FlowId[];
|
|
76
|
+
readonly tenants?: readonly TenantId[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface Budget {
|
|
80
|
+
readonly maxCostUsd?: number;
|
|
81
|
+
readonly maxLatencyMs?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Isolation posture the runtime enforces around a check's handler. Same
|
|
86
|
+
* three tiers as `ToolManifest.sandbox` in `@kindgi/tools`.
|
|
87
|
+
*
|
|
88
|
+
* Duplicated here rather than imported from `@kindgi/tools` to keep
|
|
89
|
+
* this package free of a tools dependency. Keep the shape literally
|
|
90
|
+
* identical.
|
|
91
|
+
*/
|
|
92
|
+
export type SandboxMode = 'none' | 'context-isolated' | 'strict';
|
|
93
|
+
|
|
94
|
+
/** Runtime resource caps enforced by the sandbox layer at check dispatch. */
|
|
95
|
+
export interface RuntimeLimits {
|
|
96
|
+
readonly memMB: number;
|
|
97
|
+
readonly cpuMs: number;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Network egress policy honored by the sandbox during a check. */
|
|
101
|
+
export type NetworkPolicy =
|
|
102
|
+
| { readonly kind: 'none' }
|
|
103
|
+
| { readonly kind: 'allowlist'; readonly hosts: readonly string[] }
|
|
104
|
+
| { readonly kind: 'unrestricted' };
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* JSON Schema for a typed `needs` slot. Author-time Zod is compiled to
|
|
108
|
+
* this at build (`z.toJSONSchema()`).
|
|
109
|
+
*/
|
|
110
|
+
export type JsonSchema = Readonly<Record<string, unknown>>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Discriminated typed-dependency declarations mirroring the Tool
|
|
114
|
+
* manifest's `TypedNeeds` shape (five slots); every slot is optional.
|
|
115
|
+
*/
|
|
116
|
+
export interface TypedNeeds {
|
|
117
|
+
readonly env?: Readonly<Record<string, JsonSchema>>;
|
|
118
|
+
readonly secrets?: Readonly<Record<string, JsonSchema>>;
|
|
119
|
+
readonly config?: Readonly<Record<string, JsonSchema>>;
|
|
120
|
+
readonly capabilities?: readonly string[];
|
|
121
|
+
readonly bindings?: readonly string[];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Handler-artifact pointer for the guardrail's CHECK implementation.
|
|
126
|
+
* Same shape as Tool's `CodeArtifactRef` — discriminated on `kind`:
|
|
127
|
+
*
|
|
128
|
+
* - `'oci'` — production. Populated by the deploy pipeline.
|
|
129
|
+
* `modulePath` resolves inside the pinned
|
|
130
|
+
* `imageRef`; `artifactVersion` pins one deploy.
|
|
131
|
+
* - `'filesystem'` — dev-mode. Populated at dev-mode registration.
|
|
132
|
+
* `modulePath` is an absolute host path at the
|
|
133
|
+
* check module. Production servers SHOULD reject
|
|
134
|
+
* this variant.
|
|
135
|
+
*
|
|
136
|
+
* NOTE: `modulePath` points at the check handler bundle (the pack
|
|
137
|
+
* index's `checkModulePath`, see `@kindgi/handler-runtime`); the field
|
|
138
|
+
* name stays `modulePath` for wire symmetry with tools.
|
|
139
|
+
*/
|
|
140
|
+
export type CodeArtifactRef =
|
|
141
|
+
| {
|
|
142
|
+
readonly kind: 'oci';
|
|
143
|
+
readonly imageRef: string;
|
|
144
|
+
readonly modulePath: string;
|
|
145
|
+
readonly artifactVersion: string;
|
|
146
|
+
}
|
|
147
|
+
| {
|
|
148
|
+
readonly kind: 'filesystem';
|
|
149
|
+
readonly modulePath: string;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* A guardrail declaration. Same shape at runtime + in CI — one definition,
|
|
154
|
+
* two enforcement paths.
|
|
155
|
+
*
|
|
156
|
+
* `check` references a concrete check implementation:
|
|
157
|
+
* - For `zero-llm`: id of a check in the CheckRegistry (built-in or custom).
|
|
158
|
+
* - For `llm-judge`: id of a registered check of kind `llm-judge`
|
|
159
|
+
* (`defineGuardrail` resolves it); the judge itself is configured by
|
|
160
|
+
* `config` (`LlmJudgeConfig`) + `judgeCapabilities`.
|
|
161
|
+
* - For `external` and adapter kinds: an id the kind's strategy understands.
|
|
162
|
+
*
|
|
163
|
+
* `config` is check-specific — the check implementation validates it.
|
|
164
|
+
*
|
|
165
|
+
* ## Additive extensions
|
|
166
|
+
*
|
|
167
|
+
* `sandbox`, `limits`, `network`, `needsSpec`, `codeArtifactRef` are the
|
|
168
|
+
* same runtime-declaration extensions that ToolManifest carries.
|
|
169
|
+
* Guardrails are code-carrying primitives too (a check ships as a
|
|
170
|
+
* bundle at `checkModulePath` + `node_modules`), so every field applies
|
|
171
|
+
* as-is — none are excluded. The dispatch, SDK and deploy layers
|
|
172
|
+
* populate + honor them; consumers that don't know about them ignore the fields.
|
|
173
|
+
*/
|
|
174
|
+
export interface Guardrail {
|
|
175
|
+
/**
|
|
176
|
+
* Globally-unique guardrail identifier. Convention:
|
|
177
|
+
* `<pack-id>.<guardrail-name>` (kebab-case, dot-namespaced). See the
|
|
178
|
+
* `GuardrailId` brand for the naming rule.
|
|
179
|
+
*/
|
|
180
|
+
readonly id: GuardrailId;
|
|
181
|
+
/** Short human-readable label shown in violation UI + audit logs. */
|
|
182
|
+
readonly name?: string;
|
|
183
|
+
/** Prose describing what the guardrail guarantees + what happens on violation. Surfaced to reviewers when the guardrail fires. */
|
|
184
|
+
readonly description?: string;
|
|
185
|
+
/**
|
|
186
|
+
* `'zero-llm'` — pure function over the trace (default, fast,
|
|
187
|
+
* deterministic; the recommended kind for most safety rules).
|
|
188
|
+
* `'llm-judge'` — uses a model to score (opt-in, costs money;
|
|
189
|
+
* declare `budget` + `judgeCapabilities`). `'external'` — evaluated
|
|
190
|
+
* outside the engine by a caller-registered strategy (the built-in
|
|
191
|
+
* `external` strategy returns an `invalid-guardrail` error).
|
|
192
|
+
*/
|
|
193
|
+
readonly kind: GuardrailKind;
|
|
194
|
+
/**
|
|
195
|
+
* Reference to the concrete check implementation. String id of a
|
|
196
|
+
* `RegisteredCheck` in the runtime `CheckRegistry` — either a
|
|
197
|
+
* built-in from `@kindgi/guardrails` (`BUILT_IN_CHECK_IDS`: `must-cite`,
|
|
198
|
+
* `never-call-tool`, `max-tool-calls`, `output-matches`, `tool-order`,
|
|
199
|
+
* `required-substring`, `forbidden-substring`) or a pack-authored
|
|
200
|
+
* check registered under its id (see `defineCheck`).
|
|
201
|
+
*/
|
|
202
|
+
readonly check: string;
|
|
203
|
+
/**
|
|
204
|
+
* Check-specific configuration. Interpreted by the check
|
|
205
|
+
* implementation (validated by the check's `validateConfig`, e.g.
|
|
206
|
+
* derived from its `configSchema`, when `defineGuardrail` runs).
|
|
207
|
+
* Shape is opaque to the engine; e.g. `must-cite` reads
|
|
208
|
+
* `{minCitations?: number}`, `output-matches` reads `{pattern: string}`.
|
|
209
|
+
*/
|
|
210
|
+
readonly config?: Readonly<Record<string, unknown>>;
|
|
211
|
+
/**
|
|
212
|
+
* What the framework does when this guardrail fires — `halt`
|
|
213
|
+
* (fail the run), `retry` (re-execute the step with a
|
|
214
|
+
* `maxAttempts` cap), `escalate` (route to HITL review),
|
|
215
|
+
* `log-only` (record but don't block), `compensate` (invoke a
|
|
216
|
+
* named compensation tool). `BUILT_IN_ON_VIOLATIONS` lists the
|
|
217
|
+
* built-in values; `OnViolation` itself is an open string.
|
|
218
|
+
*/
|
|
219
|
+
readonly action: Action;
|
|
220
|
+
/**
|
|
221
|
+
* `'info'` / `'warn'` / `'error'` / `'critical'` — orthogonal to
|
|
222
|
+
* `action`. Severity is what LOGS + DASHBOARDS group by; action is
|
|
223
|
+
* what EXECUTION does. A `log-only` guardrail can still be
|
|
224
|
+
* `'critical'` — just doesn't halt.
|
|
225
|
+
*/
|
|
226
|
+
readonly severity?: GuardrailSeverity;
|
|
227
|
+
/**
|
|
228
|
+
* When this guardrail applies. `{when: 'always'}` fires everywhere;
|
|
229
|
+
* `{when: 'ci-only'}` blocks CI but not runtime; `{when: 'runtime-only'}`
|
|
230
|
+
* enforces at runtime but not CI. Per-agent / per-flow selectors
|
|
231
|
+
* narrow further (e.g. `{agents: ['acme.support-agent']}`).
|
|
232
|
+
*/
|
|
233
|
+
readonly scope?: Scope;
|
|
234
|
+
/**
|
|
235
|
+
* Cost + latency ceiling per guardrail invocation (relevant for
|
|
236
|
+
* `kind: 'llm-judge'` — zero-llm checks are free): `maxCostUsd` +
|
|
237
|
+
* `maxLatencyMs`. Declarative — not enforced by the runtime.
|
|
238
|
+
*/
|
|
239
|
+
readonly budget?: Budget;
|
|
240
|
+
/**
|
|
241
|
+
* For `kind: 'llm-judge'` — capability declaration for the judge
|
|
242
|
+
* model, routed through `@kindgi/capabilities` under the tenant policy
|
|
243
|
+
* the caller passes as `EvaluationBindings.tenantPolicy`. Enables BYO
|
|
244
|
+
* judges. Ignored for zero-llm + external.
|
|
245
|
+
*/
|
|
246
|
+
readonly judgeCapabilities?: Capability;
|
|
247
|
+
/** Isolation posture — see `SandboxMode`. */
|
|
248
|
+
readonly sandbox?: SandboxMode;
|
|
249
|
+
/** Memory + CPU caps enforced by the sandbox at check dispatch. */
|
|
250
|
+
readonly limits?: RuntimeLimits;
|
|
251
|
+
/** Network egress policy the sandbox honors while the check runs. */
|
|
252
|
+
readonly network?: NetworkPolicy;
|
|
253
|
+
/**
|
|
254
|
+
* Discriminated typed-dependency declarations (env / secrets / config /
|
|
255
|
+
* capabilities / bindings). See `TypedNeeds` for the shape.
|
|
256
|
+
*/
|
|
257
|
+
readonly needsSpec?: TypedNeeds;
|
|
258
|
+
/**
|
|
259
|
+
* Pointer at the deploy-time OCI image + module path carrying the
|
|
260
|
+
* check handler bytes. Absent for in-process declarations.
|
|
261
|
+
*/
|
|
262
|
+
readonly codeArtifactRef?: CodeArtifactRef;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Recorded events from a run that checks operate on. Callers materialize
|
|
267
|
+
* these from the run's recorded events, memory and provenance —
|
|
268
|
+
* guardrails doesn't read those directly (avoids a hard dep loop; keeps
|
|
269
|
+
* checks pure).
|
|
270
|
+
*/
|
|
271
|
+
export interface ToolCallRecord {
|
|
272
|
+
readonly toolId: ToolId;
|
|
273
|
+
readonly toolName: string;
|
|
274
|
+
readonly arguments: Readonly<Record<string, unknown>>;
|
|
275
|
+
readonly at: Timestamp;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export interface ToolResultRecord {
|
|
279
|
+
readonly toolCallId: string;
|
|
280
|
+
readonly output: unknown;
|
|
281
|
+
readonly at: Timestamp;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export interface ModelCallRecord {
|
|
285
|
+
readonly providerId: string;
|
|
286
|
+
readonly model: string;
|
|
287
|
+
readonly promptTokens: number;
|
|
288
|
+
readonly completionTokens: number;
|
|
289
|
+
readonly at: Timestamp;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* The materialised run trace a check reads. Callers assemble this at the
|
|
294
|
+
* boundary from the run's events / memory / provenance — the check
|
|
295
|
+
* itself is a pure function over this shape.
|
|
296
|
+
*
|
|
297
|
+
* Adapter checks that need data not typed here use
|
|
298
|
+
* `attributes: Record<string, unknown>` as the escape hatch.
|
|
299
|
+
*/
|
|
300
|
+
export interface RunTrace {
|
|
301
|
+
readonly runId: RunId;
|
|
302
|
+
readonly tenantId: TenantId;
|
|
303
|
+
/**
|
|
304
|
+
* Content-scope anchor. Threaded to
|
|
305
|
+
* `bindings.compliance.emit()` when a violation surfaces so
|
|
306
|
+
* evidence records land under the same project as the run.
|
|
307
|
+
* Optional; when absent, the violation emit is skipped.
|
|
308
|
+
*/
|
|
309
|
+
readonly projectId?: ProjectId;
|
|
310
|
+
readonly agentId?: AgentId;
|
|
311
|
+
readonly flowId?: FlowId;
|
|
312
|
+
/** Final assistant output text. Present when the run produced text. */
|
|
313
|
+
readonly output?: string;
|
|
314
|
+
readonly toolCalls: readonly ToolCallRecord[];
|
|
315
|
+
readonly toolResults: readonly ToolResultRecord[];
|
|
316
|
+
readonly modelCalls: readonly ModelCallRecord[];
|
|
317
|
+
/**
|
|
318
|
+
* The user input that opened the turn / flow invocation. Populated
|
|
319
|
+
* by the agent runtime (`@kindgi/agents`); optional for runs that
|
|
320
|
+
* have no user turn.
|
|
321
|
+
*/
|
|
322
|
+
readonly userInput?: string;
|
|
323
|
+
/**
|
|
324
|
+
* Facts pulled by the agent's retrieval intents before the model
|
|
325
|
+
* call. Enables consistency guardrails (e.g. "every citation in
|
|
326
|
+
* output appears in retrieved.factIds").
|
|
327
|
+
*/
|
|
328
|
+
readonly retrievedFactIds?: readonly string[];
|
|
329
|
+
/**
|
|
330
|
+
* Conversation id for multi-turn context. Undefined for one-shot
|
|
331
|
+
* runs that don't belong to a conversation.
|
|
332
|
+
*/
|
|
333
|
+
readonly conversationId?: string;
|
|
334
|
+
/**
|
|
335
|
+
* 1-indexed turn number within the conversation. Undefined outside
|
|
336
|
+
* agent conversations.
|
|
337
|
+
*/
|
|
338
|
+
readonly turnNumber?: number;
|
|
339
|
+
/** Cumulative USD cost for the turn / run. */
|
|
340
|
+
readonly totalCostUsd?: number;
|
|
341
|
+
/** Wall-clock duration in milliseconds. */
|
|
342
|
+
readonly durationMs?: number;
|
|
343
|
+
/**
|
|
344
|
+
* Whether this evaluation is happening in CI or at runtime. Determines
|
|
345
|
+
* which `scope.when` values apply.
|
|
346
|
+
*/
|
|
347
|
+
readonly mode: 'ci' | 'runtime';
|
|
348
|
+
/** Free-form attributes checks may consult. Use for niche data not typed above. */
|
|
349
|
+
readonly attributes?: Readonly<Record<string, unknown>>;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Runtime bindings passed alongside the RunTrace so llm-judge guardrails
|
|
354
|
+
* can invoke a model and any guardrail can emit compliance evidence.
|
|
355
|
+
*
|
|
356
|
+
* All fields optional — a `zero-llm` guardrail needs none of them. Callers
|
|
357
|
+
* wire up only what they actually use.
|
|
358
|
+
*/
|
|
359
|
+
export interface EvaluationBindings {
|
|
360
|
+
/** Required for `kind: 'llm-judge'` guardrails — resolves + invokes the judge. */
|
|
361
|
+
readonly providerRegistry?: ProviderRegistry;
|
|
362
|
+
/**
|
|
363
|
+
* Aborted when the caller stops waiting: the agent turn was
|
|
364
|
+
* cancelled, or ran past its wall-clock budget. A check that calls out
|
|
365
|
+
* (a judge model, a service) passes it on, so a slow call doesn't
|
|
366
|
+
* hold the turn; the llm-judge strategy passes it to the model call.
|
|
367
|
+
*/
|
|
368
|
+
readonly abortSignal?: AbortSignal;
|
|
369
|
+
/**
|
|
370
|
+
* Optional — when present and the trace carries a `projectId`, every
|
|
371
|
+
* failed check emits a `guardrail-violation` compliance evidence
|
|
372
|
+
* record (passing checks emit nothing).
|
|
373
|
+
*/
|
|
374
|
+
readonly compliance?: ComplianceProvider;
|
|
375
|
+
/**
|
|
376
|
+
* Override the judge model directly (bypasses the router). Useful for
|
|
377
|
+
* tests + hermetic pinning; production should route through the registry.
|
|
378
|
+
*/
|
|
379
|
+
readonly judgeProvider?: ModelProvider;
|
|
380
|
+
/**
|
|
381
|
+
* The tenant's model-routing policy (provider / model allow and deny
|
|
382
|
+
* lists, `regionAllow`, caps). When present, llm-judge models are
|
|
383
|
+
* routed under it, and an explicit `judgeProvider` must satisfy it too
|
|
384
|
+
* — a judge never sends the run to a model the tenant doesn't allow.
|
|
385
|
+
*/
|
|
386
|
+
readonly tenantPolicy?: TenantPolicy;
|
|
387
|
+
/**
|
|
388
|
+
* Optional execution-strategy registry. When present, the engine
|
|
389
|
+
* dispatches `guardrail.kind` through this registry instead of the
|
|
390
|
+
* built-in strategies (zero-llm / llm-judge / external). Callers extend
|
|
391
|
+
* by seeding built-ins + adapter strategies. See execution-strategy.ts.
|
|
392
|
+
*/
|
|
393
|
+
readonly strategies?: import('./execution-strategy.js').ExecutionStrategyRegistry;
|
|
394
|
+
/**
|
|
395
|
+
* Optional action-handler registry. When present, the engine invokes
|
|
396
|
+
* the appropriate handler after evaluating each guardrail so custom
|
|
397
|
+
* actions (`'hitl-review'`, `'redact-then-continue'`, etc.) fire.
|
|
398
|
+
* Absent → the engine records the action in EvaluationResult but does
|
|
399
|
+
* not invoke a handler; the caller layer consults the action.
|
|
400
|
+
*/
|
|
401
|
+
readonly actions?: import('./action-handler.js').ActionHandlerRegistry;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** Result of a single check evaluation. */
|
|
405
|
+
export interface CheckResult {
|
|
406
|
+
readonly passed: boolean;
|
|
407
|
+
readonly reason?: string;
|
|
408
|
+
/** For llm-judge checks: the raw response text from the judge. */
|
|
409
|
+
readonly judgeResponse?: string;
|
|
410
|
+
/** Structured attributes attached to the result (evidence + logs). */
|
|
411
|
+
readonly attributes?: Readonly<Record<string, unknown>>;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** Result of evaluating a guardrail against a trace, including action to take. */
|
|
415
|
+
export interface EvaluationResult {
|
|
416
|
+
readonly guardrailId: GuardrailId;
|
|
417
|
+
readonly result: CheckResult;
|
|
418
|
+
/** The action the caller should apply — pre-computed from `guardrail.action`. */
|
|
419
|
+
readonly action: OnViolation | 'noop';
|
|
420
|
+
readonly severity: GuardrailSeverity;
|
|
421
|
+
readonly at: Timestamp;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* The signature checks implement. Pure function — same input yields same
|
|
426
|
+
* result. LLM-judge implementations are async and take bindings for
|
|
427
|
+
* capability routing.
|
|
428
|
+
*/
|
|
429
|
+
export type CheckFunction = (
|
|
430
|
+
config: Readonly<Record<string, unknown>>,
|
|
431
|
+
trace: RunTrace,
|
|
432
|
+
bindings: EvaluationBindings,
|
|
433
|
+
) => Promise<CheckResult>;
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* A registered check — has an id + optional config validator + evaluator.
|
|
437
|
+
* Config validation runs when the guardrail is defined; the evaluator
|
|
438
|
+
* runs at check time.
|
|
439
|
+
*/
|
|
440
|
+
export interface RegisteredCheck {
|
|
441
|
+
readonly id: string;
|
|
442
|
+
readonly kind: GuardrailKind;
|
|
443
|
+
readonly evaluate: CheckFunction;
|
|
444
|
+
readonly validateConfig?: (config: unknown) => string | undefined;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Registry mapping check id → implementation. Built-in checks are
|
|
449
|
+
* pre-populated; consumers can register custom checks at pack init.
|
|
450
|
+
*/
|
|
451
|
+
export interface CheckRegistry {
|
|
452
|
+
register(check: RegisteredCheck): void;
|
|
453
|
+
get(id: string): RegisteredCheck | undefined;
|
|
454
|
+
list(): readonly RegisteredCheck[];
|
|
455
|
+
}
|