j-chim Claude Fable 5 commited on
Commit
4a8e900
Β·
1 Parent(s): dae359e

Add the grey recognized tier to the verified badge

Browse files

Same mark, two tones: accent for submitter-validated results, grey for
results ingested directly from a known public leaderboard's official
API without submitter validation. Tooltip copy distinguishes the tiers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

app/evaluators/[...id]/page.tsx CHANGED
@@ -11,7 +11,7 @@ import type { EvalHierarchy } from "@/lib/backend-artifacts"
11
  import type { BenchmarkCard } from "@/lib/benchmark-schema"
12
  import { fetchBenchmarkMetadata, fetchEvalHierarchy, fetchEvalList } from "@/lib/dashboard-data-client"
13
  import type { BenchmarkEvalListItem } from "@/lib/eval-processing"
14
- import { getEvalsForEvaluator, verifiedEvalIds } from "@/lib/evaluators"
15
 
16
  function EvaluatorDetailInner() {
17
  const params = useParams()
@@ -159,7 +159,7 @@ function EvaluatorDetailInner() {
159
  <div className="kicker">Evaluator</div>
160
  <h1 className="ec-page-h1 inline-flex items-center gap-2">
161
  {name}
162
- {isVerified && <VerifiedBadge verified size="md" />}
163
  </h1>
164
  <div
165
  className="mb-5 flex flex-wrap items-center gap-3 font-mono text-[11px] uppercase tracking-[0.12em]"
 
11
  import type { BenchmarkCard } from "@/lib/benchmark-schema"
12
  import { fetchBenchmarkMetadata, fetchEvalHierarchy, fetchEvalList } from "@/lib/dashboard-data-client"
13
  import type { BenchmarkEvalListItem } from "@/lib/eval-processing"
14
+ import { getEvalsForEvaluator, isRecognizedEvaluator, verifiedEvalIds } from "@/lib/evaluators"
15
 
16
  function EvaluatorDetailInner() {
17
  const params = useParams()
 
159
  <div className="kicker">Evaluator</div>
160
  <h1 className="ec-page-h1 inline-flex items-center gap-2">
161
  {name}
162
+ <VerifiedBadge verified={isVerified} recognized={isRecognizedEvaluator(name)} size="md" />
163
  </h1>
164
  <div
165
  className="mb-5 flex flex-wrap items-center gap-3 font-mono text-[11px] uppercase tracking-[0.12em]"
components/eval-card.tsx CHANGED
@@ -19,7 +19,7 @@ import {
19
  } from "lucide-react"
20
  import Link from "next/link"
21
  import { routeIdToPath } from "@/lib/utils"
22
- import { evaluatorSlug } from "@/lib/evaluators"
23
  import type { BenchmarkEvalListItem } from "@/lib/eval-processing"
24
  import { getTagColor, tagLabel } from "@/lib/benchmark-schema"
25
 
@@ -278,9 +278,12 @@ export function EvalCard({ summary, delayMs = 0 }: EvalCardProps) {
278
  >
279
  {name}
280
  </Link>
281
- {verifiedEvaluators.has(name) ? (
282
- <VerifiedBadge verified size="sm" className="ml-1 align-middle" />
283
- ) : null}
 
 
 
284
  </span>
285
  ))}
286
  </span>
 
19
  } from "lucide-react"
20
  import Link from "next/link"
21
  import { routeIdToPath } from "@/lib/utils"
22
+ import { evaluatorSlug, isRecognizedEvaluator } from "@/lib/evaluators"
23
  import type { BenchmarkEvalListItem } from "@/lib/eval-processing"
24
  import { getTagColor, tagLabel } from "@/lib/benchmark-schema"
25
 
 
278
  >
279
  {name}
280
  </Link>
281
+ <VerifiedBadge
282
+ verified={verifiedEvaluators.has(name)}
283
+ recognized={isRecognizedEvaluator(name)}
284
+ size="sm"
285
+ className="ml-1 align-middle"
286
+ />
287
  </span>
288
  ))}
289
  </span>
components/eval-detail.tsx CHANGED
@@ -54,7 +54,7 @@ import {
54
  import type { BenchmarkCard, SourceData } from "@/lib/benchmark-schema"
55
  import { tagLabel } from "@/lib/benchmark-schema"
56
  import type { BenchmarkEvalSummary, ModelResultForBenchmark } from "@/lib/eval-processing"
57
- import { evaluatorSlug } from "@/lib/evaluators"
58
  import type { ComparisonIndex, EvalHierarchy } from "@/lib/backend-artifacts"
59
  import type { HierarchyEvalLocation } from "@/lib/hierarchy-lookup"
60
  import { PolicyOverview } from "@/components/policy-overview"
@@ -1111,9 +1111,12 @@ export function EvalDetail({
1111
  <span key={name} style={{ color: "var(--fg)" }}>
1112
  {i > 0 ? ", " : null}
1113
  <EvaluatorName display={name} linkName={resolveEvaluatorName(name)} />
1114
- {verifiedEvaluators.has(name) ? (
1115
- <VerifiedBadge verified size="sm" className="ml-1 align-middle" />
1116
- ) : null}
 
 
 
1117
  </span>
1118
  ))}
1119
  {evaluatorList.length > 2 ? (
@@ -2022,7 +2025,14 @@ export function EvalDetail({
2022
  {sourceTypeLabel}
2023
  </span>
2024
  )}
2025
- <VerifiedBadge verified={modelResult.result?.is_verified_evaluator} size="sm" />
 
 
 
 
 
 
 
2026
  </span>
2027
  ) : (
2028
  <span style={{ color: "var(--fg-subtle)" }}>β€”</span>
@@ -2998,6 +3008,10 @@ function MultiMetricLeaderboard({
2998
  />
2999
  <VerifiedBadge
3000
  verified={Object.values(row.verified ?? {}).some(Boolean)}
 
 
 
 
3001
  size="sm"
3002
  />
3003
  </span>
 
54
  import type { BenchmarkCard, SourceData } from "@/lib/benchmark-schema"
55
  import { tagLabel } from "@/lib/benchmark-schema"
56
  import type { BenchmarkEvalSummary, ModelResultForBenchmark } from "@/lib/eval-processing"
57
+ import { evaluatorSlug, isRecognizedEvaluator } from "@/lib/evaluators"
58
  import type { ComparisonIndex, EvalHierarchy } from "@/lib/backend-artifacts"
59
  import type { HierarchyEvalLocation } from "@/lib/hierarchy-lookup"
60
  import { PolicyOverview } from "@/components/policy-overview"
 
1111
  <span key={name} style={{ color: "var(--fg)" }}>
1112
  {i > 0 ? ", " : null}
1113
  <EvaluatorName display={name} linkName={resolveEvaluatorName(name)} />
1114
+ <VerifiedBadge
1115
+ verified={verifiedEvaluators.has(name)}
1116
+ recognized={isRecognizedEvaluator(name)}
1117
+ size="sm"
1118
+ className="ml-1 align-middle"
1119
+ />
1120
  </span>
1121
  ))}
1122
  {evaluatorList.length > 2 ? (
 
2025
  {sourceTypeLabel}
2026
  </span>
2027
  )}
2028
+ <VerifiedBadge
2029
+ verified={modelResult.result?.is_verified_evaluator}
2030
+ recognized={isRecognizedEvaluator(
2031
+ modelResult.source_metadata?.source_name
2032
+ ?? modelResult.source_metadata?.source_organization_name,
2033
+ )}
2034
+ size="sm"
2035
+ />
2036
  </span>
2037
  ) : (
2038
  <span style={{ color: "var(--fg-subtle)" }}>β€”</span>
 
3008
  />
3009
  <VerifiedBadge
3010
  verified={Object.values(row.verified ?? {}).some(Boolean)}
3011
+ recognized={isRecognizedEvaluator(
3012
+ row.source_metadata?.source_name
3013
+ ?? row.source_metadata?.source_organization_name,
3014
+ )}
3015
  size="sm"
3016
  />
3017
  </span>
components/evaluator-table.tsx CHANGED
@@ -4,7 +4,7 @@ import Link from "next/link"
4
  import { ArrowUpRight, ChevronDown, ChevronUp, ChevronsUpDown } from "lucide-react"
5
 
6
  import { VerifiedBadge } from "@/components/signals/verified-badge"
7
- import type { EvaluatorGroup } from "@/lib/evaluators"
8
  import { cn } from "@/lib/utils"
9
 
10
  export type EvaluatorTableSortCol = "name" | "evals" | "verified"
@@ -84,7 +84,11 @@ export function EvaluatorTable({ rows, sortCol, sortDir, onSort, verifiedOnly }:
84
  <span className="font-semibold text-[14px] text-[color:var(--fg)] group-hover:text-[color:var(--accent)] transition-colors">
85
  {row.name}
86
  </span>
87
- {row.isVerified && <VerifiedBadge verified size="sm" />}
 
 
 
 
88
  </div>
89
  </Link>
90
  </td>
 
4
  import { ArrowUpRight, ChevronDown, ChevronUp, ChevronsUpDown } from "lucide-react"
5
 
6
  import { VerifiedBadge } from "@/components/signals/verified-badge"
7
+ import { isRecognizedEvaluator, type EvaluatorGroup } from "@/lib/evaluators"
8
  import { cn } from "@/lib/utils"
9
 
10
  export type EvaluatorTableSortCol = "name" | "evals" | "verified"
 
84
  <span className="font-semibold text-[14px] text-[color:var(--fg)] group-hover:text-[color:var(--accent)] transition-colors">
85
  {row.name}
86
  </span>
87
+ <VerifiedBadge
88
+ verified={row.isVerified}
89
+ recognized={isRecognizedEvaluator(row.name)}
90
+ size="sm"
91
+ />
92
  </div>
93
  </Link>
94
  </td>
components/signals/verified-badge.tsx CHANGED
@@ -47,6 +47,38 @@ export type VerifiedBadgeDesign =
47
  | "chip"
48
  export type VerifiedBadgeSize = "sm" | "md"
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  const ICON_SIZE: Record<VerifiedBadgeSize, string> = {
51
  sm: "h-3.5 w-3.5",
52
  md: "h-4 w-4",
@@ -61,17 +93,26 @@ export function verifiedTooltipCopy(_mode: "research" | "policy"): string {
61
  return "Submitted by the organization that ran this evaluation."
62
  }
63
 
 
 
 
 
 
 
64
  function IconOnly({
65
  design,
66
  size,
 
67
  className,
68
  }: {
69
  design: VerifiedBadgeDesign
70
  size: VerifiedBadgeSize
 
71
  className?: string
72
  }) {
73
  const sz = ICON_SIZE[size]
74
- const base = "inline-flex shrink-0 items-center justify-center align-middle text-[var(--accent)]"
 
75
 
76
  switch (design) {
77
  case "tile":
@@ -81,7 +122,8 @@ function IconOnly({
81
  return (
82
  <span
83
  className={cn(
84
- "inline-flex shrink-0 items-center justify-center rounded-[3px] bg-[var(--accent)] align-middle text-[var(--accent-fg)]",
 
85
  size === "md" ? "h-[18px] w-[18px]" : "h-4 w-4",
86
  className
87
  )}
@@ -109,7 +151,8 @@ function IconOnly({
109
  return (
110
  <span
111
  className={cn(
112
- "inline-flex shrink-0 items-center justify-center rounded-[3px] border border-[var(--accent)]/55 align-middle text-[var(--accent)]",
 
113
  size === "md" ? "h-[18px] w-[18px]" : "h-4 w-4",
114
  className
115
  )}
@@ -122,7 +165,8 @@ function IconOnly({
122
  return (
123
  <span
124
  className={cn(
125
- "inline-flex shrink-0 items-center align-middle text-[var(--accent)] border-b border-[var(--accent)]/40 leading-none",
 
126
  className
127
  )}
128
  >
@@ -162,14 +206,21 @@ function BadgeCheckScalloped({ className }: { className?: string }) {
162
 
163
  export function VerifiedBadge({
164
  verified,
 
165
  design = "check",
166
  size = "sm",
167
  withTooltip = true,
168
- label = "Verified",
169
  className,
170
  }: {
171
  /** The per-result `is_verified` boolean. Null/false/undefined β†’ renders nothing. */
172
  verified?: boolean | null
 
 
 
 
 
 
173
  design?: VerifiedBadgeDesign
174
  size?: VerifiedBadgeSize
175
  withTooltip?: boolean
@@ -180,11 +231,14 @@ export function VerifiedBadge({
180
  // Hooks must run unconditionally; guard on the value afterwards.
181
  const { mode } = useAudienceMode()
182
 
183
- if (!verified) {
 
184
  return null
185
  }
186
 
187
- const tooltip = verifiedTooltipCopy(mode)
 
 
188
  // Screen-reader text mirrors the tooltip so the two never drift. `label`
189
  // ("Verified evaluator") only surfaces visually on the tag/chip designs.
190
  const ariaLabel = tooltip
@@ -194,7 +248,7 @@ export function VerifiedBadge({
194
  if (ICON_ONLY.includes(design)) {
195
  node = (
196
  <span aria-label={ariaLabel} role="img" className="inline-flex">
197
- <IconOnly design={design} size={size} className={className} />
198
  </span>
199
  )
200
  } else if (design === "tag") {
@@ -204,14 +258,14 @@ export function VerifiedBadge({
204
  <span
205
  className={cn(
206
  "inline-flex shrink-0 items-center gap-1 rounded-[2px] border px-1.5 py-0.5 align-middle",
207
- "border-[var(--accent)]/40 text-[var(--accent)]",
208
  "font-mono text-[10px] font-semibold uppercase tracking-[0.12em]",
209
  className
210
  )}
211
  aria-label={ariaLabel}
212
  >
213
  <Check className={size === "md" ? "h-3.5 w-3.5" : "h-3 w-3"} strokeWidth={3} />
214
- {label}
215
  </span>
216
  )
217
  } else {
@@ -220,13 +274,13 @@ export function VerifiedBadge({
220
  <Badge
221
  className={cn(
222
  "shrink-0 gap-1 rounded-full border-transparent align-middle",
223
- "bg-[var(--accent)] text-[var(--accent-fg)] hover:bg-[var(--accent-hover)]",
224
  className
225
  )}
226
  aria-label={ariaLabel}
227
  >
228
  <Check className={ICON_SIZE[size]} strokeWidth={3} />
229
- {label}
230
  </Badge>
231
  )
232
  }
 
47
  | "chip"
48
  export type VerifiedBadgeSize = "sm" | "md"
49
 
50
+ /**
51
+ * Two trust tiers share the same mark, distinguished by colour:
52
+ * - "verified" (accent/blue): submitter-validated results.
53
+ * - "recognized" (grey): known public-leaderboard sources we ingest
54
+ * directly (Artificial Analysis, LLM Stats,
55
+ * HF Open LLM v2, Global-MMLU-Lite) that are
56
+ * not submitter-verified.
57
+ */
58
+ type BadgeTone = "verified" | "recognized"
59
+
60
+ const TONE_CLASSES: Record<
61
+ BadgeTone,
62
+ { text: string; tileBg: string; glyphBorder: string; tickUnderline: string; tagBorder: string; chipBg: string }
63
+ > = {
64
+ verified: {
65
+ text: "text-[var(--accent)]",
66
+ tileBg: "bg-[var(--accent)] text-[var(--accent-fg)]",
67
+ glyphBorder: "border-[var(--accent)]/55 text-[var(--accent)]",
68
+ tickUnderline: "text-[var(--accent)] border-[var(--accent)]/40",
69
+ tagBorder: "border-[var(--accent)]/40 text-[var(--accent)]",
70
+ chipBg: "bg-[var(--accent)] text-[var(--accent-fg)] hover:bg-[var(--accent-hover)]",
71
+ },
72
+ recognized: {
73
+ text: "text-[color:var(--fg-muted)]",
74
+ tileBg: "bg-[color:var(--fg-muted)] text-[var(--accent-fg)]",
75
+ glyphBorder: "border-[color:var(--fg-muted)]/55 text-[color:var(--fg-muted)]",
76
+ tickUnderline: "text-[color:var(--fg-muted)] border-[color:var(--fg-muted)]/40",
77
+ tagBorder: "border-[color:var(--fg-muted)]/40 text-[color:var(--fg-muted)]",
78
+ chipBg: "bg-[color:var(--fg-muted)] text-[var(--accent-fg)]",
79
+ },
80
+ }
81
+
82
  const ICON_SIZE: Record<VerifiedBadgeSize, string> = {
83
  sm: "h-3.5 w-3.5",
84
  md: "h-4 w-4",
 
93
  return "Submitted by the organization that ran this evaluation."
94
  }
95
 
96
+ export function recognizedTooltipCopy(_mode: "research" | "policy"): string {
97
+ // Grey tier: the result was ingested directly from a known source's
98
+ // official API, but the submitter has not been validated.
99
+ return "Imported from this organization's official API."
100
+ }
101
+
102
  function IconOnly({
103
  design,
104
  size,
105
+ tone,
106
  className,
107
  }: {
108
  design: VerifiedBadgeDesign
109
  size: VerifiedBadgeSize
110
+ tone: BadgeTone
111
  className?: string
112
  }) {
113
  const sz = ICON_SIZE[size]
114
+ const tc = TONE_CLASSES[tone]
115
+ const base = cn("inline-flex shrink-0 items-center justify-center align-middle", tc.text)
116
 
117
  switch (design) {
118
  case "tile":
 
122
  return (
123
  <span
124
  className={cn(
125
+ "inline-flex shrink-0 items-center justify-center rounded-[3px] align-middle",
126
+ tc.tileBg,
127
  size === "md" ? "h-[18px] w-[18px]" : "h-4 w-4",
128
  className
129
  )}
 
151
  return (
152
  <span
153
  className={cn(
154
+ "inline-flex shrink-0 items-center justify-center rounded-[3px] border align-middle",
155
+ tc.glyphBorder,
156
  size === "md" ? "h-[18px] w-[18px]" : "h-4 w-4",
157
  className
158
  )}
 
165
  return (
166
  <span
167
  className={cn(
168
+ "inline-flex shrink-0 items-center align-middle border-b leading-none",
169
+ tc.tickUnderline,
170
  className
171
  )}
172
  >
 
206
 
207
  export function VerifiedBadge({
208
  verified,
209
+ recognized,
210
  design = "check",
211
  size = "sm",
212
  withTooltip = true,
213
+ label,
214
  className,
215
  }: {
216
  /** The per-result `is_verified` boolean. Null/false/undefined β†’ renders nothing. */
217
  verified?: boolean | null
218
+ /**
219
+ * Grey fallback tier: result/org comes from a recognized public leaderboard
220
+ * (see lib/evaluators.ts RECOGNIZED_EVALUATOR_NAMES) but isn't submitter-
221
+ * verified. Only takes effect when `verified` is falsy; both falsy β†’ null.
222
+ */
223
+ recognized?: boolean | null
224
  design?: VerifiedBadgeDesign
225
  size?: VerifiedBadgeSize
226
  withTooltip?: boolean
 
231
  // Hooks must run unconditionally; guard on the value afterwards.
232
  const { mode } = useAudienceMode()
233
 
234
+ const tone: BadgeTone | null = verified ? "verified" : recognized ? "recognized" : null
235
+ if (!tone) {
236
  return null
237
  }
238
 
239
+ const tc = TONE_CLASSES[tone]
240
+ const tooltip = tone === "verified" ? verifiedTooltipCopy(mode) : recognizedTooltipCopy(mode)
241
+ const visibleLabel = label ?? (tone === "verified" ? "Verified" : "Recognized")
242
  // Screen-reader text mirrors the tooltip so the two never drift. `label`
243
  // ("Verified evaluator") only surfaces visually on the tag/chip designs.
244
  const ariaLabel = tooltip
 
248
  if (ICON_ONLY.includes(design)) {
249
  node = (
250
  <span aria-label={ariaLabel} role="img" className="inline-flex">
251
+ <IconOnly design={design} size={size} tone={tone} className={className} />
252
  </span>
253
  )
254
  } else if (design === "tag") {
 
258
  <span
259
  className={cn(
260
  "inline-flex shrink-0 items-center gap-1 rounded-[2px] border px-1.5 py-0.5 align-middle",
261
+ tc.tagBorder,
262
  "font-mono text-[10px] font-semibold uppercase tracking-[0.12em]",
263
  className
264
  )}
265
  aria-label={ariaLabel}
266
  >
267
  <Check className={size === "md" ? "h-3.5 w-3.5" : "h-3 w-3"} strokeWidth={3} />
268
+ {visibleLabel}
269
  </span>
270
  )
271
  } else {
 
274
  <Badge
275
  className={cn(
276
  "shrink-0 gap-1 rounded-full border-transparent align-middle",
277
+ tc.chipBg,
278
  className
279
  )}
280
  aria-label={ariaLabel}
281
  >
282
  <Check className={ICON_SIZE[size]} strokeWidth={3} />
283
+ {visibleLabel}
284
  </Badge>
285
  )
286
  }
lib/evaluators.ts CHANGED
@@ -19,6 +19,30 @@
19
 
20
  import type { BenchmarkEvalListItem } from "@/lib/eval-processing"
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  export interface EvaluatorGroup {
23
  /** Canonical org name as it appears in `evaluator_names`. */
24
  name: string
 
19
 
20
  import type { BenchmarkEvalListItem } from "@/lib/eval-processing"
21
 
22
+ /**
23
+ * "Recognized" evaluator orgs β€” public leaderboards whose results we ingest
24
+ * directly but which are not submitter-verified. They get the grey
25
+ * VerifiedBadge tier (vs the blue verified one). Keys are the view-layer
26
+ * evaluator/source names of the four ingested sources:
27
+ * artificial_analysis β†’ "Artificial Analysis"
28
+ * llm_stats β†’ "LLM Stats"
29
+ * hfopenllm_v2 β†’ "Hugging Face"
30
+ * global-mmlu-lite β†’ "kaggle"
31
+ * Matched case-insensitively (see isRecognizedEvaluator).
32
+ */
33
+ export const RECOGNIZED_EVALUATOR_NAMES = new Set([
34
+ "artificial analysis",
35
+ "llm stats",
36
+ "hugging face",
37
+ "kaggle",
38
+ ])
39
+
40
+ /** True when the org name is one of the recognized leaderboard sources. */
41
+ export function isRecognizedEvaluator(name: string | null | undefined): boolean {
42
+ if (!name) return false
43
+ return RECOGNIZED_EVALUATOR_NAMES.has(name.trim().toLowerCase())
44
+ }
45
+
46
  export interface EvaluatorGroup {
47
  /** Canonical org name as it appears in `evaluator_names`. */
48
  name: string