Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/app/api/citable/route.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import { NextResponse } from "next/server";
import { getBenchmarks } from "@/data/benchmarks";
import { SITE } from "@/data/site";
import { AllBenchmarksDraftError } from "@/lib/spec";
import { fieldValue, leader, headlineSentence } from "@/lib/citation";
import {
fieldValue,
headlineSentence,
isInsufficient,
leader,
} from "@/lib/citation";
import { clientKey, rateLimit, tooManyRequests } from "@/lib/rate-limit";

export const runtime = "nodejs";
Expand DownExpand Up@@ -47,17 +52,21 @@ export async function GET(req: Request) {
throw err;
}
const data = benches.map((b) => {
const top = leader(b);
const insufficient = isInsufficient(b);
const top = insufficient ? null : leader(b);
const status: "live" | "draft" | "insufficient" = insufficient
? "insufficient"
: b.status;
return {
slug: b.slug,
title: b.title,
category: b.category,
metric: b.metric,
unit: b.unit,
status: b.status,
value: fieldValue(b),
status,
value: insufficient ? null : fieldValue(b),
leader: top ? { name: top.name, slug: top.slug, value: top.value } : null,
sampleSize: b.sampleSize,
sampleSize: insufficient ? 0 : b.sampleSize,
asOf: b.lastRunAt,
headline: headlineSentence(b),
url: `${SITE.url}/benchmarks/${b.slug}`,
Expand Down
21 changes: 18 additions & 3 deletions src/app/api/llm-context/route.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,12 @@ import { getBenchmarks } from "@/data/benchmarks";
import { SITE } from "@/data/site";
import { AllBenchmarksDraftError } from "@/lib/spec";
import { fmtUnit } from "@/lib/format";
import { fieldValue, headlineSentence, leader } from "@/lib/citation";
import {
fieldValue,
headlineSentence,
isInsufficient,
leader,
} from "@/lib/citation";
import { clientKey, rateLimit, tooManyRequests } from "@/lib/rate-limit";

export const runtime = "nodejs";
Expand DownExpand Up@@ -67,11 +72,15 @@ export async function GET(req: Request) {
lines.push(`- Metric: ${b.metric} (${b.unit})`);
lines.push(`- Page: ${SITE.url}/benchmarks/${b.slug}`);
lines.push(`- JSON: ${SITE.url}/api/stat/${b.slug}`);
lines.push(`- Status: ${b.status}`);
const insufficient = isInsufficient(b);
const reportedStatus: "live" | "draft" | "insufficient" = insufficient
? "insufficient"
: b.status;
lines.push(`- Status: ${reportedStatus}`);

const v = fieldValue(b);
const lead = leader(b);
if (v != null && lead) {
if (!insufficient && v != null && lead) {
lines.push(`- Headline: ${headlineSentence(b)}`);
lines.push("");
lines.push(`**Rankings (p50, 24h):**`);
Expand All@@ -89,6 +98,12 @@ export async function GET(req: Request) {
)}, success ${r.successRate.toFixed(1)}%, sample ${r.sampleSize ?? "n/a"})`,
);
}
} else if (insufficient) {
// Surface the same insufficient sentence the other citable surfaces
// emit, so an LLM that pastes this Markdown into context never sees
// a fabricated winner for a bench whose harness lacks data.
lines.push(`- Headline: ${headlineSentence(b)}`);
lines.push(`- Insufficient samples to rank providers yet.`);
} else {
lines.push(`- ${b.status === "draft" ? "Draft (no live data yet)" : "Awaiting samples"}.`);
}
Expand Down
94 changes: 65 additions & 29 deletions src/app/api/mcp/[transport]/route.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,6 +7,7 @@ import {
citationQuote,
fieldValue,
headlineSentence,
isInsufficient,
leader,
sparklineFor,
} from "@/lib/citation";
Expand DownExpand Up@@ -208,15 +209,19 @@ const mcpHandler = createMcpHandler(
async () => {
const benches = (await getBenchmarks()).filter((b) => b.editorialStatus === "live");
const rows = benches.map((b) => {
const top = leader(b);
const insufficient = isInsufficient(b);
const top = insufficient ? null : leader(b);
const status: "live" | "draft" | "insufficient" = insufficient
? "insufficient"
: b.status;
return {
slug: b.slug,
title: b.title,
category: b.category,
metric: b.metric,
unit: b.unit,
status: b.status,
value: fieldValue(b),
status,
value: insufficient ? null : fieldValue(b),
leader: top,
headline: headlineSentence(b),
url: `${SITE.url}/benchmarks/${b.slug}`,
Expand DownExpand Up@@ -279,25 +284,39 @@ const mcpHandler = createMcpHandler(
isError: true,
};
}
const top = leader(b);
const insufficient = isInsufficient(b);
const top = insufficient ? null : leader(b);
const status: "live" | "draft" | "insufficient" = insufficient
? "insufficient"
: b.status;
const rankings = insufficient
? b.results.map((r) => ({
name: r.name,
slug: r.slug,
ms: { p50: null, p90: null, p99: null, mean: null },
successRate: r.successRate,
}))
: b.results
.filter((r) => r.ms.p50 > 0)
.sort((a, c) =>
b.higherIsBetter ? c.ms.p50 - a.ms.p50 : a.ms.p50 - c.ms.p50,
)
.map((r) => ({
name: r.name,
slug: r.slug,
ms: r.ms,
successRate: r.successRate,
}));
const payload = {
slug: b.slug,
title: b.title,
metric: b.metric,
unit: b.unit,
status: b.status,
value: fieldValue(b),
status,
value: insufficient ? null : fieldValue(b),
leader: top,
rankings: b.results
.filter((r) => r.ms.p50 > 0)
.sort((a, c) => (b.higherIsBetter ? c.ms.p50 - a.ms.p50 : a.ms.p50 - c.ms.p50))
.map((r) => ({
name: r.name,
slug: r.slug,
ms: r.ms,
successRate: r.successRate,
})),
sparkline: sparklineFor(b, top?.slug),
rankings,
sparkline: insufficient ? [] : sparklineFor(b, top?.slug),
headline: headlineSentence(b),
quote: citationQuote(b, SITE.url),
pageUrl: `${SITE.url}/benchmarks/${b.slug}`,
Expand DownExpand Up@@ -458,10 +477,15 @@ const mcpHandler = createMcpHandler(
],
};
}
const top = leader(b);
const ranked = b.results
.filter((r) => r.ms.p50 > 0)
.sort((a, c) => (b.higherIsBetter ? c.ms.p50 - a.ms.p50 : a.ms.p50 - c.ms.p50));
const insufficient = isInsufficient(b);
const top = insufficient ? null : leader(b);
const ranked = insufficient
? []
: b.results
.filter((r) => r.ms.p50 > 0)
.sort((a, c) =>
b.higherIsBetter ? c.ms.p50 - a.ms.p50 : a.ms.p50 - c.ms.p50,
);

const md: string[] = [];
md.push(`# ${b.title}`);
Expand DownExpand Up@@ -501,21 +525,33 @@ const mcpHandler = createMcpHandler(

// We attach both Markdown (default rendering) and JSON (structured
// access) so clients can pick whichever matches their context.
const status: "live" | "draft" | "insufficient" = insufficient
? "insufficient"
: b.status;
const payload = {
slug: b.slug,
title: b.title,
metric: b.metric,
unit: b.unit,
value: fieldValue(b),
status,
value: insufficient ? null : fieldValue(b),
leader: top,
rankings: ranked.map((r) => ({
name: r.name,
slug: r.slug,
ms: r.ms,
successRate: r.successRate,
sampleSize: r.sampleSize,
})),
sparkline: sparklineFor(b, top?.slug),
rankings: insufficient
? b.results.map((r) => ({
name: r.name,
slug: r.slug,
ms: { p50: null, p90: null, p99: null, mean: null },
successRate: r.successRate,
sampleSize: r.sampleSize ?? null,
}))
: ranked.map((r) => ({
name: r.name,
slug: r.slug,
ms: r.ms,
successRate: r.successRate,
sampleSize: r.sampleSize,
})),
sparkline: insufficient ? [] : sparklineFor(b, top?.slug),
headline: headlineSentence(b),
quote: citationQuote(b, SITE.url),
pageUrl: `${SITE.url}/benchmarks/${b.slug}`,
Expand Down
65 changes: 50 additions & 15 deletions src/app/api/stat/[slug]/route.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,6 +5,7 @@ import {
citationQuote,
fieldValue,
headlineSentence,
isInsufficient,
leader,
sparklineFor,
} from "@/lib/citation";
Expand All@@ -19,6 +20,16 @@ export const revalidate = 60;
* Single benchmark as a citable atomic unit. Designed to fit into one
* agent tool call: ranked providers, sparkline, methodology link,
* pre-formatted attribution string, and stable citation URL.
*
* Status field semantics:
* "live" - usable measurement, leader / value populated.
* "draft" - spec author has not published (editorialStatus draft).
* "insufficient" - editorially live but the harness has no usable
* sample yet (every provider p50 = 0, or runtime
* status flipped to draft mid-cycle). value, leader
* and rankings p50 are nulled so a consumer cannot
* accidentally cite a fabricated winner. The shape
* of the response is preserved.
*/
export async function GET(
req: Request,
Expand All@@ -42,30 +53,54 @@ export async function GET(
);
}

const top = leader(b);
const insufficient = isInsufficient(b);
const top = insufficient ? null : leader(b);
const value = insufficient ? null : fieldValue(b);
// Status surfaced to consumers: "insufficient" wins over the raw
// runtime "live" flag when the predicate fires, so /api/stat stops
// claiming live data for a bench whose harness has nothing to show.
const status: "live" | "draft" | "insufficient" = insufficient
? "insufficient"
: b.status;

// Rankings: when insufficient we still return one entry per provider
// (shape preserved for any consumer that diff-tracks the provider set)
// but every p50 is nulled to drive home that no comparison is possible.
const rankings = insufficient
? b.results.map((r) => ({
name: r.name,
slug: r.slug,
ms: { p50: null, p90: null, p99: null, mean: null },
successRate: r.successRate,
sampleSize: r.sampleSize ?? null,
}))
: b.results
.filter((r) => r.ms.p50 > 0)
.sort((a, c) =>
b.higherIsBetter ? c.ms.p50 - a.ms.p50 : a.ms.p50 - c.ms.p50,
)
.map((r) => ({
name: r.name,
slug: r.slug,
ms: r.ms,
successRate: r.successRate,
sampleSize: r.sampleSize,
}));

const payload = {
slug: b.slug,
title: b.title,
subtitle: b.subtitle,
category: b.category,
metric: b.metric,
unit: b.unit,
status: b.status,
status,
higherIsBetter: b.higherIsBetter,
value: fieldValue(b),
value,
leader: top,
rankings: b.results
.filter((r) => r.ms.p50 > 0)
.sort((a, c) => (b.higherIsBetter ? c.ms.p50 - a.ms.p50 : a.ms.p50 - c.ms.p50))
.map((r) => ({
name: r.name,
slug: r.slug,
ms: r.ms,
successRate: r.successRate,
sampleSize: r.sampleSize,
})),
sparkline: sparklineFor(b, top?.slug),
sampleSize: b.sampleSize,
rankings,
sparkline: insufficient ? [] : sparklineFor(b, top?.slug),
sampleSize: insufficient ? 0 : b.sampleSize,
asOf: b.lastRunAt,
headline: headlineSentence(b),
quote: citationQuote(b, SITE.url),
Expand Down
11 changes: 9 additions & 2 deletions src/app/benchmarks/[slug]/page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,7 +16,7 @@ import { ShareSection } from "@/components/share-section";
import { ExportVideoSection } from "@/components/export-video-section";
import { ReportSection } from "@/components/report-section";
import { CATEGORY_COLOR } from "@/lib/category-colors";
import { headlineSentence } from "@/lib/citation";
import { headlineSentence, isInsufficient } from "@/lib/citation";
import { capDescription } from "@/lib/seo-text";
import { getBenchCreatedAt } from "@/lib/seo/bench-dates";
import { SITE } from "@/data/site";
Expand DownExpand Up@@ -172,6 +172,10 @@ export default async function BenchmarkPage({

const isDraft = benchmark.status === "draft";
const isAwaiting = isDraft && benchmark.editorialStatus === "live";
// Insufficient: editorially live, runtime might say "live" too, but the
// shared predicate decided no provider has a usable p50. Drives the
// pill above the H1 and the headline degradation downstream.
const insufficient = isInsufficient(benchmark);
// Cap the "more benchmarks" rail at 6 items so it doesn't turn into
// an endless single-column scroll on mobile (with 18 benches the old
// unlimited list rendered 17 full cards stacked). Prefer same-category
Expand DownExpand Up@@ -321,7 +325,10 @@ export default async function BenchmarkPage({
{isAwaiting ? "awaiting samples" : "draft"}
</span>
)}
{!isDraft && (
{!isDraft && insufficient && (
<span className="text-ink-faint">insufficient samples</span>
)}
{!isDraft && !insufficient && (
<span className="ml-auto">
<LiveIndicator lastRunAt={benchmark.lastRunAt} slug={benchmark.slug} />
</span>
Expand Down
Loading
Loading