fix(drift): render interpretation objects safely
This commit is contained in:
@@ -29,8 +29,8 @@ interface DriftReport {
|
||||
high_count: number
|
||||
medium_count: number
|
||||
info_count: number
|
||||
interpretation: string | null
|
||||
status: 'pending' | 'acknowledged' | 'rolled_back' | 'adopted' | 'ignored'
|
||||
interpretation: DriftInterpretationValue
|
||||
status: 'pending' | 'resolved' | 'acknowledged' | 'rolled_back' | 'adopted' | 'ignored'
|
||||
created_at: string
|
||||
resolved_at: string | null
|
||||
}
|
||||
@@ -42,9 +42,19 @@ interface ScanResult {
|
||||
medium_count: number
|
||||
info_count: number
|
||||
has_critical_drift: boolean
|
||||
interpretation: string | null
|
||||
interpretation: DriftInterpretationValue
|
||||
}
|
||||
|
||||
type DriftInterpretationValue =
|
||||
| string
|
||||
| {
|
||||
intent?: string | null
|
||||
explanation?: string | null
|
||||
risk?: string | null
|
||||
confidence?: number | null
|
||||
}
|
||||
| null
|
||||
|
||||
interface DriftFingerprintState {
|
||||
namespace?: string
|
||||
fingerprint?: string
|
||||
@@ -98,6 +108,19 @@ const fmtTime = (iso: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
const formatInterpretation = (value: DriftInterpretationValue) => {
|
||||
if (!value) return null
|
||||
if (typeof value === 'string') return value
|
||||
const meta = [
|
||||
value.intent,
|
||||
value.risk,
|
||||
typeof value.confidence === 'number' ? `${Math.round(value.confidence * 100)}%` : null,
|
||||
].filter(Boolean).join(' / ')
|
||||
const explanation = value.explanation || ''
|
||||
if (meta && explanation) return `${meta} — ${explanation}`
|
||||
return meta || explanation || null
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Sub-components
|
||||
// =============================================================================
|
||||
@@ -140,6 +163,7 @@ function DriftLevelBadge({ high, medium, info, t }: {
|
||||
function StatusBadge({ status, t }: { status: DriftReport['status']; t: (k: string) => string }) {
|
||||
const styles: Record<string, string> = {
|
||||
pending: 'bg-status-warning/10 text-status-warning border-status-warning/20',
|
||||
resolved: 'bg-status-healthy/10 text-status-healthy border-status-healthy/20',
|
||||
acknowledged: 'bg-neutral-100 text-neutral-500 border-neutral-200',
|
||||
rolled_back: 'bg-status-healthy/10 text-status-healthy border-status-healthy/20',
|
||||
adopted: 'bg-status-healthy/10 text-status-healthy border-status-healthy/20',
|
||||
@@ -340,9 +364,9 @@ export function DriftPanel() {
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{scanResult.interpretation && (
|
||||
{formatInterpretation(scanResult.interpretation) && (
|
||||
<p className="mt-1.5 text-neutral-600 font-normal pl-5">
|
||||
{scanResult.interpretation}
|
||||
{formatInterpretation(scanResult.interpretation)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -397,9 +421,9 @@ export function DriftPanel() {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{report.interpretation && (
|
||||
{formatInterpretation(report.interpretation) && (
|
||||
<p className="mt-2 text-[11px] text-neutral-500 pl-1 border-l-2 border-neutral-100">
|
||||
{report.interpretation}
|
||||
{formatInterpretation(report.interpretation)}
|
||||
</p>
|
||||
)}
|
||||
<div className="flex items-center gap-4 mt-2 text-[10px] text-neutral-400">
|
||||
|
||||
Reference in New Issue
Block a user