BID · Console
Baseline · Intelligence · Decision
src/agents/decision/delivery-distribution/schema.ts 2,761 bytes · typescript
/**
 * Delivery & Distribution — input and output schemas (Std 2 + Std 11).
 */

import { z } from 'zod';
import { visualizationOutputSchema } from '../visualization/schema.js';

export const deliveryDistributionInputSchema = visualizationOutputSchema;
export type DeliveryDistributionInput = z.infer<typeof deliveryDistributionInputSchema>;

export const dispatchSchema = z.object({
  dispatchId: z.string(),
  visualizationReference: z.string(),
  recommendationReference: z.string(),
  deliveryRuleApplied: z.string(),
  channel: z.string(),
  channelOutcome: z.object({
    ok: z.boolean(),
    channelMessage: z.string().optional(),
    error: z.object({ category: z.string(), message: z.string() }).optional(),
  }),
  recipient: z.string(),
  audienceTier: z.string(),
  severity: z.string(),
  contentKind: z.string(),
  contentReference: z.string(),
  dispatchedAt: z.string(),
  acknowledgmentRequired: z.boolean(),
  acknowledgmentWindowSec: z.number().optional(),
  acknowledgmentState: z.enum(['pending', 'acknowledged', 'not-applicable', 'failed']),
  cadence: z
    .object({
      maxPerDay: z.number().optional(),
      maxPerWeek: z.number().optional(),
      enforced: z.boolean(),
      enforcementNote: z.string().optional(),
    })
    .optional(),
  fallbackUsed: z.boolean(),
  reasoningLineage: z.array(z.string()),
  confidence: z.number().min(0).max(1),
  flags: z.array(z.string()),
});
export type Dispatch = z.infer<typeof dispatchSchema>;

export const deliveryGapSchema = z.object({
  visualizationReference: z.string(),
  reason: z.enum([
    'no-rule-matched',
    'channel-unavailable',
    'cadence-violation',
    'recipient-verification-failed',
    'authorization-required',
    'dispatch-failed',
  ]),
  detail: z.string(),
  triedTriggers: z.array(z.string()),
});
export type DeliveryGap = z.infer<typeof deliveryGapSchema>;

/* The dispatch audit log mirrors what the audit-log channel records
 * in src/decision/channel-registry.ts. It is also written to the
 * agent's handoff for repository persistence (spec §Std 10). */
export const dispatchAuditEntrySchema = z.object({
  at: z.string(),
  recipient: z.string(),
  audienceTier: z.string(),
  contentReference: z.string(),
  severity: z.string(),
  contentKind: z.string(),
});
export type DispatchAuditEntry = z.infer<typeof dispatchAuditEntrySchema>;

export const deliveryDistributionOutputSchema = z.object({
  dispatches: z.array(dispatchSchema),
  deliveryGapsEscalated: z.array(deliveryGapSchema),
  channelAuditLog: z.array(dispatchAuditEntrySchema),
  appliedRules: z.array(z.string()),
  channelsUsed: z.array(z.string()),
  notes: z.array(z.string()),
});
export type DeliveryDistributionOutput = z.infer<typeof deliveryDistributionOutputSchema>;