import type { Metadata } from 'next';
import Link from 'next/link';
import { SectionNav } from '@/components/layout/terminal';
import { BreadcrumbLd } from '@/components/meta/breadcrumb-ld';
import { Chip, Estimated, TierBadge } from '@/components/ui/badges';
import { DataTable, Td, Th } from '@/components/ui/data-table';
import { Container, Note, PageHeader, Section } from '@/components/ui/section';
import { Unavailable } from '@/components/ui/unavailable';
import { apiD3, safe } from '@/lib/api';
import { fmtAgo, fmtInt, humanize } from '@/lib/format';
import { eventLabel, routes, SITE_NAME, TIER_LABELS } from '@/lib/site';
import type { MethodologyD3 } from '@/lib/types';
export const metadata: Metadata = { title: 'Methodology — provenance, tiers, openness, trust, comparability, counters, events, anomalies, estimates', description: 'How AI Atlas records facts: source tiers, confidence, temporal claims and conflicts, openness definitions, benchmark trust levels and comparability rules, counter definitions, event semantics (occurred / observed / recorded), anomaly checks, hardware-fit assumptions and frontier composition.', alternates: { canonical: '/methodology' } };
export const revalidate = 3600;
/** The API may return dicts or lists for these vocabularies; normalise to rows. */
function rows(v: unknown, keyName: string): { key: string; label?: string; description?: string; extra?: Record }[] {
if (!v) return [];
if (Array.isArray(v)) return v.map((x) => (typeof x === 'string' ? { key: x } : { key: String((x as Record)[keyName] ?? (x as Record).key ?? (x as Record).name ?? ''), label: (x as Record).label as string | undefined, description: ((x as Record).description ?? (x as Record).text) as string | undefined, extra: x as Record }));
if (typeof v === 'object') return Object.entries(v as Record).map(([k, d]) => (typeof d === 'string' ? { key: k, description: d } : { key: k, ...(d as Record), extra: d as Record }));
return [];
}
function Defs({ obj, mono = true }: { obj: Record | undefined | null; mono?: boolean }) {
const entries = Object.entries(obj ?? {}).filter(([, v]) => typeof v === 'string');
if (!entries.length) return ;
return (
{entries.map(([k, v]) => (
- {k}
- {String(v)}
))}
);
}
function Keys({ items }: { items: unknown }) {
if (!Array.isArray(items) || !items.length) return —;
return (
{items.map((k) => (
{String(k)}
))}
);
}
const NAV = [
{ id: 'principles', label: 'Principles' },
{ id: 'tiers', label: 'Tiers' },
{ id: 'confidence', label: 'Confidence' },
{ id: 'openness', label: 'Openness' },
{ id: 'trust', label: 'Trust levels' },
{ id: 'comparability', label: 'Comparability' },
{ id: 'counters', label: 'Counters' },
{ id: 'events', label: 'Events' },
{ id: 'anomalies', label: 'Anomalies' },
{ id: 'estimates', label: 'Hardware fit' },
{ id: 'frontier', label: 'Frontier' },
{ id: 'quality', label: 'Quality' },
{ id: 'extractors', label: 'Extraction' },
];
export default async function MethodologyPage() {
const m: MethodologyD3 | null = await safe(apiD3.methodology());
const tiers = rows(m?.tiers, 'tier');
const conf = rows(m?.confidence_levels, 'key');
const events = rows(m?.event_types, 'event_type');
const extractors = rows(m?.extractors, 'key');
const comp = (m?.comparability ?? {}) as Record;
const hf = (m?.hardware_fit ?? {}) as { assumptions?: string[]; bytes_per_param?: Record; reserved_gb?: number };
return (
quality v{m.quality_version} : undefined} />
{!m && }
{m?.principles?.length ? (
{m.principles.map((p) => (
- {p}
))}
) : (
AI Atlas is built from first-party connectors that read public documents directly. Every document is snapshotted and archived; every fact points back to a snapshot. Facts are temporal claims — a property, a value, a source, a tier, a confidence, an extractor and a validity interval. Missing means missing.
)}
{m && tiers.length ? (
| Tier |
Meaning |
Description |
{tiers.map((t, i) => (
|
|
{t.label ?? TIER_LABELS[Number(t.key)] ?? humanize(t.key)} |
{t.description ?? '—'} |
))}
) : (
)}
A higher tier can supersede a lower one; the reverse produces a flagged conflict. Both claims are kept.
{m && conf.length ? (
{conf.map((c, i) => (
- {c.key}
- {c.description ?? c.label ?? '—'}
))}
) : (
)}
{m?.status_vocabulary?.length ? (
Status vocabulary:
) : null}
{m?.openness ? (
<>
| Category |
Label |
Definition |
{m.openness.categories.map((c) => (
| {c} |
{m.openness?.labels?.[c] ?? humanize(c)} |
{m.openness?.definitions?.[c] ?? '—'} |
))}
Dimensions:
{m.licence_categories?.length ? (
Licence categories:
) : null}
>
) : (
)}
{m?.trust_levels?.length ? (
{(m.trust_levels as { key: string; label: string; description?: string }[]).map((t) => (
- {t.key}
- {t.label}{t.description ? ` — ${t.description}` : ''}
))}
) : (
)}
{Object.keys(comp).length ? (
<>
{(['comparable', 'partially-comparable', 'not-comparable'] as const).filter((k) => typeof comp[k] === 'string').map((k) => (
- {k}
- {String(comp[k])}
))}
{typeof comp.leaderboard === 'string' && (
- Leaderboards
- {comp.leaderboard}
)}
>
) : (
)}
{m && events.length ? (
| Event type |
Label |
Category |
Importance |
Recorded |
Last seen |
{events.map((e, i) => (
| {e.key} |
{e.label ?? e.description ?? eventLabel(e.key)} |
{String(e.extra?.category ?? '—')} |
{e.extra?.importance !== undefined ? String(e.extra.importance) : '—'} |
{e.extra?.count !== undefined ? fmtInt(e.extra.count) : '—'} |
{typeof e.extra?.last_seen_at === 'string' ? fmtAgo(e.extra.last_seen_at) : '—'} |
))}
) : (
)}
{m?.anomaly_checks?.length ? (
| Check |
Severity |
Description |
{m.anomaly_checks.map((c) => (
| {c.check} |
{c.severity}
|
{c.description} |
))}
) : (
)}
Hardware fit is an estimate >}>
{hf.assumptions?.length ? (
{hf.assumptions.map((a) => (
- {a}
))}
) : (
)}
{hf.bytes_per_param && (
Bytes per parameter:{' '}
{Object.entries(hf.bytes_per_param).map(([k, v], i) => (
{i > 0 && ' · '}
{k} {v}
))}
{hf.reserved_gb !== undefined && <> · reserved {hf.reserved_gb} GB>}
)}
{typeof m?.frontier === 'string' ? {m.frontier}
: m?.frontier ? } mono={false} /> : }
{m?.find_a_model && (
<>
Find-a-model rules
>
)}
{m && m.metrics?.length > 0 ? (
| Metric |
Definition |
Version |
{m.metrics.map((x, i) => (
| {String(x.key ?? x.name ?? '—')} |
{String(x.description ?? x.formula ?? x.label ?? '—')}{x.unit ? · {String(x.unit)} : null} |
{x.version !== undefined ? String(x.version) : '—'} |
))}
) : (
)}
{m?.expected_fields && (
<>
Expected fields per type (completeness)
{Object.entries(m.expected_fields).map(([t, fields]) => (
- {t}
-
))}
>
)}
);
}