97575cc9c0
Kanonisches Compliance-Datenmodell, Impressum-Agent als Referenz: - CheckStatus-Enum + Finding.status GETRENNT von severity (Verdikt ≠ Risiko) - Unbestimmte Rechtsform (weder Text noch Wizard) → INSUFFICIENT_EVIDENCE (INFO) statt hartem HIGH-FAIL; legal_form_dependent-Gate + detect_legal_form_present - §18-MStV-Graubereich (Corporate-Blog via has_editorial_content) → POSSIBLY_APPLICABLE (LOW Prüf-Hinweis); 3-stufig via scope_disposition - Recommendations nur aus echten FAILs; mc_insufficient/mc_possibly-Aggregate - Frontend: Verdikt-Pill + Coverage-Vokabular - 19 neue Tests (test_four_status.py, AgentFindingCard); CI-Suite 204 grün, v3 25 / GT 13 unverändert Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
'use client'
|
|
|
|
/**
|
|
* "Was wurde geprüft" — listet alle MCs eines Agents mit ihrem Status.
|
|
* Standardmäßig collapsed; zeigt sofort, was Methodik des Agents war.
|
|
*/
|
|
|
|
import React, { useState } from 'react'
|
|
|
|
import type { McCoverage } from './_agentTypes'
|
|
|
|
const STATUS_COLOR: Record<string, string> = {
|
|
ok: '#10b981',
|
|
na: '#94a3b8',
|
|
skipped: '#cbd5e1',
|
|
high: '#dc2626',
|
|
medium: '#f59e0b',
|
|
low: '#3b82f6',
|
|
insufficient_evidence: '#64748b',
|
|
possibly_applicable: '#ca8a04',
|
|
}
|
|
|
|
const STATUS_LABEL: Record<string, string> = {
|
|
ok: 'OK',
|
|
na: 'n/a',
|
|
skipped: 'übersprungen',
|
|
high: 'HIGH',
|
|
medium: 'MEDIUM',
|
|
low: 'LOW',
|
|
insufficient_evidence: 'unklar',
|
|
possibly_applicable: 'evtl. relevant',
|
|
}
|
|
|
|
export function AgentMcCoverage({ coverage }: { coverage: McCoverage[] }) {
|
|
const [open, setOpen] = useState(false)
|
|
if (!coverage?.length) return null
|
|
return (
|
|
<div className="border rounded bg-slate-50">
|
|
<button
|
|
onClick={() => setOpen(o => !o)}
|
|
className="w-full text-left px-3 py-2 text-xs font-semibold uppercase text-gray-700 flex justify-between items-center"
|
|
>
|
|
<span>Was wurde geprüft? ({coverage.length} MCs)</span>
|
|
<span className="text-gray-400">{open ? '▾' : '▸'}</span>
|
|
</button>
|
|
{open && (
|
|
<div className="border-t bg-white p-2 space-y-0.5 max-h-60 overflow-y-auto">
|
|
{coverage.map(c => (
|
|
<div key={c.mc_id} className="flex items-center gap-2 text-xs">
|
|
<span
|
|
className="w-2 h-2 rounded-full inline-block"
|
|
style={{ background: STATUS_COLOR[c.status] || '#cbd5e1' }}
|
|
/>
|
|
<code className="text-gray-500">{c.mc_id}</code>
|
|
<span className="text-gray-700">
|
|
{STATUS_LABEL[c.status] || c.status}
|
|
</span>
|
|
{c.reason && (
|
|
<span className="text-gray-400 italic">— {c.reason}</span>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|