@lore-co/core 0.1.17 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/auth-schemas.d.ts +92 -4
  2. package/dist/auth-schemas.d.ts.map +1 -1
  3. package/dist/auth-schemas.js +77 -0
  4. package/dist/auth-schemas.js.map +1 -1
  5. package/dist/canonical-json.d.ts +19 -0
  6. package/dist/canonical-json.d.ts.map +1 -0
  7. package/dist/canonical-json.js +228 -0
  8. package/dist/canonical-json.js.map +1 -0
  9. package/dist/conflict-detector.d.ts.map +1 -1
  10. package/dist/conflict-detector.js +30 -14
  11. package/dist/conflict-detector.js.map +1 -1
  12. package/dist/engine.d.ts +38 -6
  13. package/dist/engine.d.ts.map +1 -1
  14. package/dist/engine.js +118 -25
  15. package/dist/engine.js.map +1 -1
  16. package/dist/guard-schemas.d.ts +217 -1
  17. package/dist/guard-schemas.d.ts.map +1 -1
  18. package/dist/guard-schemas.js +92 -11
  19. package/dist/guard-schemas.js.map +1 -1
  20. package/dist/index.d.ts +5 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +5 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/integration-contract.d.ts +612 -0
  25. package/dist/integration-contract.d.ts.map +1 -0
  26. package/dist/integration-contract.js +679 -0
  27. package/dist/integration-contract.js.map +1 -0
  28. package/dist/native-coding-agents.d.ts +1 -1
  29. package/dist/native-coding-agents.d.ts.map +1 -1
  30. package/dist/native-coding-agents.js +2 -0
  31. package/dist/native-coding-agents.js.map +1 -1
  32. package/dist/operational-metrics.d.ts +165 -0
  33. package/dist/operational-metrics.d.ts.map +1 -0
  34. package/dist/operational-metrics.js +216 -0
  35. package/dist/operational-metrics.js.map +1 -0
  36. package/dist/pilot-schemas.d.ts +80 -0
  37. package/dist/pilot-schemas.d.ts.map +1 -1
  38. package/dist/platform-admin-schemas.d.ts +171 -8
  39. package/dist/platform-admin-schemas.d.ts.map +1 -1
  40. package/dist/platform-admin-schemas.js +89 -1
  41. package/dist/platform-admin-schemas.js.map +1 -1
  42. package/dist/ports.d.ts +85 -8
  43. package/dist/ports.d.ts.map +1 -1
  44. package/dist/ports.js +231 -1
  45. package/dist/ports.js.map +1 -1
  46. package/dist/reliability-schemas.d.ts +723 -0
  47. package/dist/reliability-schemas.d.ts.map +1 -0
  48. package/dist/reliability-schemas.js +750 -0
  49. package/dist/reliability-schemas.js.map +1 -0
  50. package/dist/schemas.d.ts +205 -0
  51. package/dist/schemas.d.ts.map +1 -1
  52. package/dist/schemas.js +166 -1
  53. package/dist/schemas.js.map +1 -1
  54. package/dist/session-schemas.d.ts +80 -0
  55. package/dist/session-schemas.d.ts.map +1 -1
  56. package/dist/snapshot-schemas.d.ts +3503 -0
  57. package/dist/snapshot-schemas.d.ts.map +1 -0
  58. package/dist/snapshot-schemas.js +507 -0
  59. package/dist/snapshot-schemas.js.map +1 -0
  60. package/package.json +21 -1
@@ -0,0 +1,750 @@
1
+ import { z } from "zod";
2
+ import { GuardActionSchema } from "./guard-schemas.js";
3
+ import { redactUnknown } from "./redaction.js";
4
+ import { AgentMessageSchema, MemoryScopeSchema, } from "./schemas.js";
5
+ export const RELIABILITY_CONTRACT_VERSION = "reliability-v1";
6
+ export const RELIABILITY_V1_MEDIA_TYPE = "application/vnd.lore.reliability-v1+json";
7
+ export const CAPTURE_EXTRACT_JOB_VERSION = "capture-extract-v1";
8
+ export const MEMORY_EMBED_JOB_VERSION = "memory-embed-v1";
9
+ export const ReliabilityContractVersionSchema = z.literal(RELIABILITY_CONTRACT_VERSION);
10
+ export const ReliabilityOperationSchema = z.enum([
11
+ "capture",
12
+ "retrieval",
13
+ "guard",
14
+ ]);
15
+ export const ReliabilityStatusSchema = z.enum([
16
+ "ok",
17
+ "degraded",
18
+ "blocked",
19
+ "overridden",
20
+ "failed",
21
+ ]);
22
+ export const ReliabilitySourceSchema = z.enum([
23
+ "live",
24
+ "cache",
25
+ "local_queue",
26
+ "none",
27
+ ]);
28
+ export const ReliabilityFallbackModeSchema = z.enum([
29
+ "none",
30
+ "live_lexical",
31
+ "cached_context",
32
+ "cached_policy",
33
+ "local_queue",
34
+ "break_glass",
35
+ ]);
36
+ export const ReliabilityReasonCodeSchema = z.enum([
37
+ "live_success",
38
+ "idempotent_replay",
39
+ "semantic_unavailable",
40
+ "lexical_fallback",
41
+ "live_unavailable",
42
+ "cached_context",
43
+ "cached_policy",
44
+ "no_usable_cache",
45
+ "capture_queued",
46
+ "local_persistence_failed",
47
+ "governed_rule",
48
+ "policy_unavailable",
49
+ "policy_expired",
50
+ "user_override",
51
+ "invalid_response",
52
+ "integration_unsupported",
53
+ ]);
54
+ const KnownFreshnessFields = {
55
+ asOf: z.iso.datetime({ offset: true }),
56
+ ageMs: z.number().int().nonnegative(),
57
+ validUntil: z.iso.datetime({ offset: true }).nullable(),
58
+ };
59
+ export const ReliabilityFreshnessSchema = z.discriminatedUnion("state", [
60
+ z
61
+ .object({
62
+ state: z.literal("fresh"),
63
+ ...KnownFreshnessFields,
64
+ })
65
+ .strict(),
66
+ z
67
+ .object({
68
+ state: z.literal("stale"),
69
+ ...KnownFreshnessFields,
70
+ })
71
+ .strict(),
72
+ z
73
+ .object({
74
+ state: z.literal("unknown"),
75
+ asOf: z.null(),
76
+ ageMs: z.null(),
77
+ validUntil: z.null(),
78
+ })
79
+ .strict(),
80
+ ]);
81
+ export const ReliabilityPolicyReferenceSchema = z
82
+ .discriminatedUnion("source", [
83
+ z
84
+ .object({
85
+ source: z.literal("live"),
86
+ version: z.string().trim().min(1).max(200),
87
+ loadedAt: z.iso.datetime({ offset: true }),
88
+ validUntil: z.iso.datetime({ offset: true }).nullable(),
89
+ })
90
+ .strict(),
91
+ z
92
+ .object({
93
+ source: z.literal("cache"),
94
+ version: z.string().trim().min(1).max(200),
95
+ loadedAt: z.iso.datetime({ offset: true }),
96
+ validUntil: z.iso.datetime({ offset: true }),
97
+ })
98
+ .strict(),
99
+ z
100
+ .object({
101
+ source: z.literal("none"),
102
+ version: z.null(),
103
+ loadedAt: z.null(),
104
+ validUntil: z.null(),
105
+ })
106
+ .strict(),
107
+ ])
108
+ .superRefine((policy, context) => {
109
+ if (policy.source !== "none" &&
110
+ policy.validUntil !== null &&
111
+ Date.parse(policy.validUntil) <= Date.parse(policy.loadedAt)) {
112
+ context.addIssue({
113
+ code: "custom",
114
+ path: ["validUntil"],
115
+ message: "Policy validity must end after it was loaded",
116
+ });
117
+ }
118
+ });
119
+ const FALLBACK_REASON = {
120
+ live_lexical: "lexical_fallback",
121
+ cached_context: "cached_context",
122
+ cached_policy: "cached_policy",
123
+ local_queue: "capture_queued",
124
+ break_glass: "user_override",
125
+ };
126
+ export const ReliabilityMetadataSchema = z
127
+ .object({
128
+ contractVersion: ReliabilityContractVersionSchema,
129
+ operation: ReliabilityOperationSchema,
130
+ status: ReliabilityStatusSchema,
131
+ source: ReliabilitySourceSchema,
132
+ freshness: ReliabilityFreshnessSchema,
133
+ fallback: ReliabilityFallbackModeSchema,
134
+ policy: ReliabilityPolicyReferenceSchema,
135
+ reasons: z.array(ReliabilityReasonCodeSchema).min(1).max(8),
136
+ requestId: z.string().trim().min(1).max(128).nullable(),
137
+ })
138
+ .strict()
139
+ .superRefine((result, context) => {
140
+ if (new Set(result.reasons).size !== result.reasons.length) {
141
+ context.addIssue({
142
+ code: "custom",
143
+ path: ["reasons"],
144
+ message: "Reliability reason codes must be unique",
145
+ });
146
+ }
147
+ const expectedFallbackReason = FALLBACK_REASON[result.fallback];
148
+ if (expectedFallbackReason !== undefined &&
149
+ !result.reasons.includes(expectedFallbackReason)) {
150
+ context.addIssue({
151
+ code: "custom",
152
+ path: ["reasons"],
153
+ message: `Fallback ${result.fallback} requires reason ${expectedFallbackReason}`,
154
+ });
155
+ }
156
+ if (result.source === "none" && result.freshness.state !== "unknown") {
157
+ context.addIssue({
158
+ code: "custom",
159
+ path: ["freshness"],
160
+ message: "A result with no source must have unknown freshness",
161
+ });
162
+ }
163
+ if (result.source === "live" && result.freshness.state !== "fresh") {
164
+ context.addIssue({
165
+ code: "custom",
166
+ path: ["freshness"],
167
+ message: "A live result must be fresh",
168
+ });
169
+ }
170
+ if (result.source === "cache" &&
171
+ result.freshness.state === "unknown") {
172
+ context.addIssue({
173
+ code: "custom",
174
+ path: ["freshness"],
175
+ message: "A cached result must report when it was captured",
176
+ });
177
+ }
178
+ if (result.source === "local_queue" &&
179
+ result.freshness.state !== "fresh") {
180
+ context.addIssue({
181
+ code: "custom",
182
+ path: ["freshness"],
183
+ message: "A newly queued local capture must be fresh",
184
+ });
185
+ }
186
+ if (result.status === "ok" && result.source === "none") {
187
+ context.addIssue({
188
+ code: "custom",
189
+ path: ["source"],
190
+ message: "A successful result must identify a usable source",
191
+ });
192
+ }
193
+ if (result.status === "ok" && result.fallback !== "none") {
194
+ context.addIssue({
195
+ code: "custom",
196
+ path: ["fallback"],
197
+ message: "A non-degraded result cannot use a fallback",
198
+ });
199
+ }
200
+ if (result.status === "degraded" && result.fallback === "none") {
201
+ context.addIssue({
202
+ code: "custom",
203
+ path: ["fallback"],
204
+ message: "A degraded result must identify its fallback",
205
+ });
206
+ }
207
+ if (result.status === "overridden" &&
208
+ result.fallback !== "break_glass") {
209
+ context.addIssue({
210
+ code: "custom",
211
+ path: ["fallback"],
212
+ message: "An overridden result must use the break-glass fallback",
213
+ });
214
+ }
215
+ if (result.status === "failed" &&
216
+ (result.source !== "none" || result.fallback !== "none")) {
217
+ context.addIssue({
218
+ code: "custom",
219
+ path: ["status"],
220
+ message: "A failed result cannot claim a usable source or fallback",
221
+ });
222
+ }
223
+ if (result.fallback === "live_lexical" &&
224
+ result.source !== "live") {
225
+ context.addIssue({
226
+ code: "custom",
227
+ path: ["source"],
228
+ message: "A lexical fallback is still a live source",
229
+ });
230
+ }
231
+ if ((result.fallback === "cached_context" ||
232
+ result.fallback === "cached_policy") &&
233
+ result.source !== "cache") {
234
+ context.addIssue({
235
+ code: "custom",
236
+ path: ["source"],
237
+ message: "A cached fallback must identify cache as its source",
238
+ });
239
+ }
240
+ if (result.fallback === "local_queue" &&
241
+ result.source !== "local_queue") {
242
+ context.addIssue({
243
+ code: "custom",
244
+ path: ["source"],
245
+ message: "A local-queue fallback must identify the local queue",
246
+ });
247
+ }
248
+ });
249
+ const CaptureAcknowledgementFields = {
250
+ contractVersion: ReliabilityContractVersionSchema,
251
+ captureId: z.uuid(),
252
+ idempotencyKey: z.string().trim().min(1).max(500),
253
+ acknowledgedAt: z.iso.datetime({ offset: true }),
254
+ };
255
+ export const CaptureAcknowledgementSchema = z
256
+ .discriminatedUnion("state", [
257
+ z
258
+ .object({
259
+ ...CaptureAcknowledgementFields,
260
+ state: z.literal("queued_local"),
261
+ durability: z.literal("local_machine"),
262
+ replayPending: z.literal(true),
263
+ replayed: z.literal(false),
264
+ processing: z.literal("pending_upload"),
265
+ })
266
+ .strict(),
267
+ z
268
+ .object({
269
+ ...CaptureAcknowledgementFields,
270
+ state: z.literal("committed_server"),
271
+ durability: z.literal("workspace_database"),
272
+ replayPending: z.literal(false),
273
+ replayed: z.boolean(),
274
+ processing: z.enum(["pending_extraction", "completed"]),
275
+ eventId: z.uuid(),
276
+ memoryIds: z.array(z.uuid()),
277
+ })
278
+ .strict(),
279
+ ])
280
+ .superRefine((acknowledgement, context) => {
281
+ if (acknowledgement.state === "committed_server" &&
282
+ acknowledgement.processing === "pending_extraction" &&
283
+ acknowledgement.memoryIds.length > 0) {
284
+ context.addIssue({
285
+ code: "custom",
286
+ path: ["memoryIds"],
287
+ message: "Pending extraction cannot acknowledge extracted memories",
288
+ });
289
+ }
290
+ });
291
+ export const CaptureProcessingResultSchema = z
292
+ .object({
293
+ created: z.number().int().nonnegative(),
294
+ duplicates: z.number().int().nonnegative(),
295
+ reconciled: z.number().int().nonnegative(),
296
+ superseded: z.number().int().nonnegative(),
297
+ })
298
+ .strict();
299
+ const CaptureExtractMemoryIdsSchema = z.array(z.uuid()).max(10_000);
300
+ const CaptureExtractResultFields = {
301
+ memoryIds: CaptureExtractMemoryIdsSchema,
302
+ result: CaptureProcessingResultSchema,
303
+ };
304
+ const CaptureExtractMessageSchema = AgentMessageSchema.extend({
305
+ content: z.string().max(100_000),
306
+ id: z.string().trim().min(1).max(500).optional(),
307
+ }).strict();
308
+ const CaptureExtractScopeSchema = MemoryScopeSchema.extend({
309
+ organization: z.string().trim().min(1).max(200),
310
+ project: z.string().trim().min(1).max(500).optional(),
311
+ repo: z.string().trim().min(1).max(1_000).optional(),
312
+ path: z.string().trim().min(1).max(2_000).optional(),
313
+ component: z.string().trim().min(1).max(500).optional(),
314
+ }).strict();
315
+ const CaptureExtractInteractionSchema = z
316
+ .object({
317
+ agent: z.string().trim().min(1).max(100),
318
+ workspaceId: z.uuid(),
319
+ eventId: z.uuid(),
320
+ userId: z.uuid().optional(),
321
+ scope: CaptureExtractScopeSchema,
322
+ sessionId: z.string().trim().min(1).max(500),
323
+ messages: z.array(CaptureExtractMessageSchema).min(1).max(500),
324
+ })
325
+ .strict();
326
+ const CaptureRedactionFindingSchema = z
327
+ .object({
328
+ kind: z.enum([
329
+ "circular",
330
+ "pre_redacted",
331
+ "private_key",
332
+ "authorization",
333
+ "connection_url",
334
+ "jwt",
335
+ "provider_token",
336
+ "credential",
337
+ ]),
338
+ count: z.number().int().positive().max(10_000),
339
+ })
340
+ .strict();
341
+ const CaptureExtractProvenanceFields = {
342
+ connector: z.string().trim().min(1).max(100),
343
+ externalEventId: z.string().trim().min(1).max(500),
344
+ redacted: z.boolean(),
345
+ redactionFindings: z.array(CaptureRedactionFindingSchema).max(8),
346
+ };
347
+ export const CaptureExtractJobPayloadSchema = z
348
+ .discriminatedUnion("kind", [
349
+ z
350
+ .object({
351
+ jobVersion: z.literal(CAPTURE_EXTRACT_JOB_VERSION),
352
+ kind: z.literal("observation"),
353
+ captureId: z.uuid(),
354
+ eventId: z.uuid(),
355
+ idempotencyKey: z.string().trim().min(1).max(500),
356
+ requestHash: z.string().regex(/^[a-f0-9]{64}$/u),
357
+ interaction: CaptureExtractInteractionSchema,
358
+ provenance: z
359
+ .object({
360
+ ...CaptureExtractProvenanceFields,
361
+ task: z.string().max(100_000).nullable(),
362
+ })
363
+ .strict(),
364
+ })
365
+ .strict(),
366
+ z
367
+ .object({
368
+ jobVersion: z.literal(CAPTURE_EXTRACT_JOB_VERSION),
369
+ kind: z.literal("paired_turn"),
370
+ captureId: z.uuid(),
371
+ eventId: z.uuid(),
372
+ idempotencyKey: z.string().trim().min(1).max(500),
373
+ requestHash: z.string().regex(/^[a-f0-9]{64}$/u),
374
+ interaction: CaptureExtractInteractionSchema,
375
+ provenance: z
376
+ .object({
377
+ ...CaptureExtractProvenanceFields,
378
+ previousAssistantMessageId: z
379
+ .string()
380
+ .trim()
381
+ .min(1)
382
+ .max(500)
383
+ .nullable(),
384
+ })
385
+ .strict(),
386
+ })
387
+ .strict(),
388
+ ])
389
+ .superRefine((payload, context) => {
390
+ if (payload.interaction.eventId !== payload.eventId) {
391
+ context.addIssue({
392
+ code: "custom",
393
+ path: ["interaction", "eventId"],
394
+ message: "Capture interaction must bind the persisted event",
395
+ });
396
+ }
397
+ const redacted = redactUnknown(payload).value;
398
+ if (JSON.stringify(redacted) !== JSON.stringify(payload)) {
399
+ context.addIssue({
400
+ code: "custom",
401
+ path: ["interaction"],
402
+ message: "Capture extraction payload must be redacted before persistence",
403
+ });
404
+ }
405
+ });
406
+ export const CaptureExtractJobResultSchema = z
407
+ .object({
408
+ jobVersion: z.literal(CAPTURE_EXTRACT_JOB_VERSION),
409
+ captureId: z.uuid(),
410
+ eventId: z.uuid(),
411
+ ...CaptureExtractResultFields,
412
+ })
413
+ .strict();
414
+ const Sha256Schema = z.string().regex(/^[a-f0-9]{64}$/u);
415
+ export const MemoryEmbedJobPayloadV1Schema = z
416
+ .object({
417
+ jobVersion: z.literal(MEMORY_EMBED_JOB_VERSION),
418
+ workspaceId: z.uuid(),
419
+ memoryId: z.uuid(),
420
+ updatedAt: z.iso.datetime({ offset: true }),
421
+ fingerprint: Sha256Schema,
422
+ contentSha256: Sha256Schema,
423
+ provider: z.string().trim().min(1).max(100),
424
+ model: z.string().trim().min(1).max(500),
425
+ embeddingSpaceId: Sha256Schema,
426
+ dimensions: z.number().int().min(1).max(16_384),
427
+ })
428
+ .strict();
429
+ export const MemoryEmbedJobResultV1Schema = z
430
+ .object({
431
+ jobVersion: z.literal(MEMORY_EMBED_JOB_VERSION),
432
+ memoryId: z.uuid(),
433
+ embeddingSpaceId: Sha256Schema,
434
+ outcome: z.enum(["stored", "stale"]),
435
+ })
436
+ .strict();
437
+ const CaptureStatusFields = {
438
+ contractVersion: ReliabilityContractVersionSchema,
439
+ captureId: z.uuid(),
440
+ eventId: z.uuid(),
441
+ createdAt: z.iso.datetime({ offset: true }),
442
+ updatedAt: z.iso.datetime({ offset: true }),
443
+ };
444
+ export const CaptureStatusResponseSchema = z
445
+ .discriminatedUnion("processing", [
446
+ z
447
+ .object({
448
+ ...CaptureStatusFields,
449
+ processing: z.literal("pending_extraction"),
450
+ attempts: z.number().int().min(0).max(100),
451
+ })
452
+ .strict(),
453
+ z
454
+ .object({
455
+ ...CaptureStatusFields,
456
+ processing: z.literal("completed"),
457
+ attempts: z.number().int().min(1).max(100),
458
+ completedAt: z.iso.datetime({ offset: true }),
459
+ ...CaptureExtractResultFields,
460
+ })
461
+ .strict(),
462
+ z
463
+ .object({
464
+ ...CaptureStatusFields,
465
+ processing: z.literal("dead"),
466
+ attempts: z.number().int().min(1).max(100),
467
+ deadAt: z.iso.datetime({ offset: true }),
468
+ failure: z
469
+ .object({
470
+ code: z
471
+ .string()
472
+ .trim()
473
+ .min(1)
474
+ .max(100)
475
+ .regex(/^[a-z0-9][a-z0-9._-]*$/iu),
476
+ message: z.string().trim().min(1).max(500),
477
+ })
478
+ .strict(),
479
+ })
480
+ .strict(),
481
+ ])
482
+ .superRefine((status, context) => {
483
+ if (Date.parse(status.updatedAt) < Date.parse(status.createdAt)) {
484
+ context.addIssue({
485
+ code: "custom",
486
+ path: ["updatedAt"],
487
+ message: "Capture status cannot be updated before the job was created",
488
+ });
489
+ }
490
+ const terminalAt = status.processing === "completed"
491
+ ? status.completedAt
492
+ : status.processing === "dead"
493
+ ? status.deadAt
494
+ : null;
495
+ if (terminalAt !== null &&
496
+ Date.parse(terminalAt) < Date.parse(status.createdAt)) {
497
+ context.addIssue({
498
+ code: "custom",
499
+ path: [
500
+ status.processing === "completed" ? "completedAt" : "deadAt",
501
+ ],
502
+ message: "Capture job cannot terminate before it was created",
503
+ });
504
+ }
505
+ if (terminalAt !== null &&
506
+ Date.parse(terminalAt) > Date.parse(status.updatedAt)) {
507
+ context.addIssue({
508
+ code: "custom",
509
+ path: [
510
+ status.processing === "completed" ? "completedAt" : "deadAt",
511
+ ],
512
+ message: "Capture job cannot terminate after its last update",
513
+ });
514
+ }
515
+ });
516
+ export const CaptureStatusSchema = CaptureStatusResponseSchema;
517
+ export const CaptureReliabilityResultSchema = z
518
+ .object({
519
+ reliability: ReliabilityMetadataSchema,
520
+ acknowledgement: CaptureAcknowledgementSchema.nullable(),
521
+ })
522
+ .strict()
523
+ .superRefine((result, context) => {
524
+ if (result.reliability.operation !== "capture") {
525
+ context.addIssue({
526
+ code: "custom",
527
+ path: ["reliability", "operation"],
528
+ message: "A capture result must identify the capture operation",
529
+ });
530
+ }
531
+ if (result.reliability.status === "failed") {
532
+ if (result.acknowledgement !== null) {
533
+ context.addIssue({
534
+ code: "custom",
535
+ path: ["acknowledgement"],
536
+ message: "A failed capture cannot be acknowledged",
537
+ });
538
+ }
539
+ return;
540
+ }
541
+ if (result.acknowledgement === null) {
542
+ context.addIssue({
543
+ code: "custom",
544
+ path: ["acknowledgement"],
545
+ message: "A non-failed capture must include an acknowledgement",
546
+ });
547
+ return;
548
+ }
549
+ if (result.acknowledgement.state === "queued_local" &&
550
+ (result.reliability.status !== "degraded" ||
551
+ result.reliability.source !== "local_queue" ||
552
+ result.reliability.fallback !== "local_queue")) {
553
+ context.addIssue({
554
+ code: "custom",
555
+ path: ["reliability"],
556
+ message: "A locally queued capture must report degraded local-queue use",
557
+ });
558
+ }
559
+ if (result.acknowledgement.state === "committed_server" &&
560
+ (result.reliability.status !== "ok" ||
561
+ result.reliability.source !== "live" ||
562
+ result.reliability.fallback !== "none")) {
563
+ context.addIssue({
564
+ code: "custom",
565
+ path: ["reliability"],
566
+ message: "A server-committed capture must report a live success",
567
+ });
568
+ }
569
+ if (result.acknowledgement.state === "committed_server" &&
570
+ result.acknowledgement.replayed &&
571
+ !result.reliability.reasons.includes("idempotent_replay")) {
572
+ context.addIssue({
573
+ code: "custom",
574
+ path: ["reliability", "reasons"],
575
+ message: "A replayed acknowledgement must identify idempotent replay",
576
+ });
577
+ }
578
+ });
579
+ const GuardConfirmationSchema = z.discriminatedUnion("kind", [
580
+ z
581
+ .object({
582
+ kind: z.literal("approval"),
583
+ command: z.string().trim().min(1).max(500),
584
+ expiresAt: z.iso.datetime({ offset: true }),
585
+ })
586
+ .strict(),
587
+ z
588
+ .object({
589
+ kind: z.literal("break_glass"),
590
+ command: z.string().trim().min(1).max(500),
591
+ expiresAt: z.iso.datetime({ offset: true }),
592
+ })
593
+ .strict(),
594
+ ]);
595
+ export const ReliableGuardDecisionSchema = z
596
+ .discriminatedUnion("decision", [
597
+ z
598
+ .object({
599
+ decision: z.literal("allow"),
600
+ checkId: z.uuid(),
601
+ requiresConfirmation: z.literal(false),
602
+ matchedRuleIds: z.array(z.uuid()),
603
+ })
604
+ .strict(),
605
+ z
606
+ .object({
607
+ decision: z.literal("block"),
608
+ checkId: z.uuid(),
609
+ requiresConfirmation: z.literal(true),
610
+ blockingRuleIds: z.array(z.uuid()),
611
+ confirmation: GuardConfirmationSchema,
612
+ })
613
+ .strict(),
614
+ z
615
+ .object({
616
+ decision: z.literal("override"),
617
+ checkId: z.uuid(),
618
+ requiresConfirmation: z.literal(false),
619
+ overriddenRuleIds: z.array(z.uuid()),
620
+ override: z
621
+ .object({
622
+ id: z.uuid(),
623
+ reason: z.string().trim().min(1).max(1_000),
624
+ auditPending: z.boolean(),
625
+ })
626
+ .strict(),
627
+ })
628
+ .strict(),
629
+ ])
630
+ .superRefine((decision, context) => {
631
+ if (decision.decision === "block" &&
632
+ decision.confirmation.kind === "approval" &&
633
+ decision.blockingRuleIds.length === 0) {
634
+ context.addIssue({
635
+ code: "custom",
636
+ path: ["blockingRuleIds"],
637
+ message: "Rule approval requires at least one blocking rule",
638
+ });
639
+ }
640
+ });
641
+ export const GuardReliabilityResultSchema = z
642
+ .object({
643
+ reliability: ReliabilityMetadataSchema,
644
+ verdict: ReliableGuardDecisionSchema,
645
+ })
646
+ .strict()
647
+ .superRefine((result, context) => {
648
+ if (result.reliability.operation !== "guard") {
649
+ context.addIssue({
650
+ code: "custom",
651
+ path: ["reliability", "operation"],
652
+ message: "A guard result must identify the guard operation",
653
+ });
654
+ }
655
+ if (result.verdict.decision === "allow" &&
656
+ result.reliability.status !== "ok" &&
657
+ result.reliability.status !== "degraded") {
658
+ context.addIssue({
659
+ code: "custom",
660
+ path: ["reliability", "status"],
661
+ message: "An allow verdict must be successful or explicitly degraded",
662
+ });
663
+ }
664
+ if (result.verdict.decision === "block" &&
665
+ result.reliability.status !== "blocked") {
666
+ context.addIssue({
667
+ code: "custom",
668
+ path: ["reliability", "status"],
669
+ message: "A block verdict must report blocked status",
670
+ });
671
+ }
672
+ if (result.verdict.decision === "override" &&
673
+ result.reliability.status !== "overridden") {
674
+ context.addIssue({
675
+ code: "custom",
676
+ path: ["reliability", "status"],
677
+ message: "An override verdict must report overridden status",
678
+ });
679
+ }
680
+ if (result.verdict.decision === "block" &&
681
+ result.verdict.blockingRuleIds.length === 0) {
682
+ const outageReasons = [
683
+ "policy_unavailable",
684
+ "policy_expired",
685
+ "no_usable_cache",
686
+ ];
687
+ if (result.verdict.confirmation.kind !== "break_glass" ||
688
+ !result.reliability.reasons.some((reason) => outageReasons.includes(reason))) {
689
+ context.addIssue({
690
+ code: "custom",
691
+ path: ["verdict", "confirmation"],
692
+ message: "A policy-outage block must provide break-glass confirmation and an outage reason",
693
+ });
694
+ }
695
+ }
696
+ });
697
+ export const AgentReliabilityCapabilitiesSchema = z
698
+ .object({
699
+ contractVersion: ReliabilityContractVersionSchema,
700
+ agent: z.string().trim().min(1).max(100),
701
+ contextDelivery: z.enum(["none", "prompt", "pre_action"]),
702
+ captureDurability: z.enum([
703
+ "none",
704
+ "memory",
705
+ "local_disk",
706
+ "server",
707
+ ]),
708
+ guardBoundaryCoverage: z.enum(["none", "partial", "full"]),
709
+ guardedActions: z.array(GuardActionSchema),
710
+ enforcement: z.enum(["none", "context_only", "deny", "confirm"]),
711
+ stateDurability: z.enum(["none", "memory", "local_disk", "server"]),
712
+ runtimeCoverage: z.array(z.enum(["local", "cloud"])).min(1),
713
+ })
714
+ .strict()
715
+ .superRefine((capabilities, context) => {
716
+ if (capabilities.guardBoundaryCoverage === "none" &&
717
+ capabilities.guardedActions.length > 0) {
718
+ context.addIssue({
719
+ code: "custom",
720
+ path: ["guardedActions"],
721
+ message: "An integration without guard boundaries cannot list actions",
722
+ });
723
+ }
724
+ if (capabilities.guardBoundaryCoverage !== "none" &&
725
+ capabilities.guardedActions.length === 0) {
726
+ context.addIssue({
727
+ code: "custom",
728
+ path: ["guardedActions"],
729
+ message: "A guarded integration must list its covered actions",
730
+ });
731
+ }
732
+ if ((capabilities.enforcement === "deny" ||
733
+ capabilities.enforcement === "confirm") &&
734
+ capabilities.guardBoundaryCoverage === "none") {
735
+ context.addIssue({
736
+ code: "custom",
737
+ path: ["enforcement"],
738
+ message: "Enforcement requires a host mutation boundary",
739
+ });
740
+ }
741
+ if (new Set(capabilities.runtimeCoverage).size !==
742
+ capabilities.runtimeCoverage.length) {
743
+ context.addIssue({
744
+ code: "custom",
745
+ path: ["runtimeCoverage"],
746
+ message: "Runtime coverage entries must be unique",
747
+ });
748
+ }
749
+ });
750
+ //# sourceMappingURL=reliability-schemas.js.map