diff --git a/src/components/admin/review-row.tsx b/src/components/admin/review-row.tsx index b923dbd..db25153 100644 --- a/src/components/admin/review-row.tsx +++ b/src/components/admin/review-row.tsx @@ -66,6 +66,47 @@ function StatusBadge({ status }: { status: ReviewStatus }) { ) } +// ── Confidence indicator (dot + label, color-banded) ───────────────────────── +// Accepts a 0–1 score. Bands: High ≥0.85, Medium ≥0.6, Low below. + +function ConfidenceIndicator({ value }: { value: number }) { + const clamped = Math.max(0, Math.min(1, value)) + const pct = Math.round(clamped * 100) + const band = + clamped >= 0.85 + ? { dot: "bg-emerald-400", text: "text-emerald-300", label: "High confidence" } + : clamped >= 0.6 + ? { dot: "bg-amber-400", text: "text-amber-300", label: "Medium confidence" } + : { dot: "bg-rose-400", text: "text-rose-300", label: "Low confidence" } + return ( + + + {band.label} + · + {pct}% + + ) +} + +// Pulls an inline "(confidence: 0.77)" out of a rationale string. Returns the +// score normalized to 0–1 and the rationale with that fragment removed, so the +// number can be shown as a badge instead of being buried in the sentence. +function extractConfidence( + rationale: string | null | undefined +): { value: number; cleaned: string } | null { + if (!rationale) return null + const m = rationale.match(/\(\s*confidence:\s*([0-9]*\.?[0-9]+)\s*\)/i) + if (!m) return null + const raw = parseFloat(m[1]) + if (Number.isNaN(raw)) return null + const value = raw > 1 ? raw / 100 : raw + const cleaned = rationale.replace(m[0], "").replace(/\s{2,}/g, " ").trim() + return { value, cleaned } +} + // ── Node colour by type (cheap heuristic, schema-agnostic) ──────────────────── const TYPE_DOT: Record = { @@ -1159,23 +1200,32 @@ export function ReviewRow({ )} - - - Rationale - - - - {review.rationale} - - } - /> - - {review.rationale} - - - + {(() => { + const conf = extractConfidence(review.rationale) + const text = conf?.cleaned ?? review.rationale + return ( + + + + Rationale + + {conf && } + + + + {text} + + } + /> + + {text} + + + + ) + })()} )}