/**
* Visualization — input and output schemas (Std 2 + Std 11).
*/
import { z } from 'zod';
import { outputIngestionOutputSchema } from '../output-ingestion/schema.js';
export const visualizationInputSchema = outputIngestionOutputSchema;
export type VisualizationInput = z.infer<typeof visualizationInputSchema>;
export const disclosurePolicyResultSchema = z.object({
visualizationId: z.string(),
audienceTier: z.string(),
decision: z.enum(['cleared', 'restricted', 'no-policy']),
policyApplied: z.string().optional(),
detail: z.string(),
});
export type DisclosurePolicyResult = z.infer<typeof disclosurePolicyResultSchema>;
export const visualizationSpecSchema = z.object({
/** Structured chart kind from rule.action.chart_type — opaque
* to the framework, meaningful to the downstream renderer. */
chartType: z.string(),
/** Where each visual axis / channel is bound to a recommendation
* field. Copy of rule.action.data_binding plus any concrete value
* substitutions. */
dataBinding: z.record(z.unknown()),
/** Color palette identifier from rule.action.color_palette. */
colorPalette: z.string().optional(),
/** Static-image, pdf-embed, tabular fallback, etc. */
format: z.object({
primary: z.string(),
secondary: z.string().optional(),
fallback: z.string().optional(),
}),
/** Narrative wrapper with template tokens already substituted. */
narrativeWrapper: z.object({
headline: z.string(),
supporting: z.string(),
constraints: z.array(z.string()).default([]),
}),
/** Optional structured annotations the renderer should draw. */
annotations: z.array(z.string()).default([]),
});
export type VisualizationSpec = z.infer<typeof visualizationSpecSchema>;
export const visualizationSchema = z.object({
visualizationId: z.string(),
recommendationReference: z.string(),
visualizationRuleApplied: z.string(),
audienceTier: z.string(),
outputSpecification: visualizationSpecSchema,
disclosurePolicy: disclosurePolicyResultSchema,
reasoningLineage: z.array(z.string()),
confidence: z.number().min(0).max(1),
flags: z.array(z.string()),
});
export type Visualization = z.infer<typeof visualizationSchema>;
export const visualizationGapSchema = z.object({
recommendationReference: z.string(),
reason: z.enum([
'no-rule-matched',
'disclosure-blocked',
'fidelity-violation',
'template-binding-failed',
]),
detail: z.string(),
triedTriggers: z.array(z.string()),
});
export type VisualizationGap = z.infer<typeof visualizationGapSchema>;
export const visualizationOutputSchema = z.object({
visualizations: z.array(visualizationSchema),
visualizationGapsEscalated: z.array(visualizationGapSchema),
disclosurePolicyResults: z.array(disclosurePolicyResultSchema),
appliedRules: z.array(z.string()),
notes: z.array(z.string()),
});
export type VisualizationOutput = z.infer<typeof visualizationOutputSchema>;