feat(workbench): Calibration route — the gold-tether arena made visible (Wave M B2)

Consumes the B1 readers (#724). The route where you SEE 'the engine earns
the right to guess' (ADR-0175).

- list (failures-first, server-ordered): per class a reliability bar
  (Wilson floor vs the PROPOSE/SERVE θ markers — a class earns the right
  when its fill crosses the marker), correct/refused/wrong counts (wrong in
  the contradicted token), and a verdict pill (earned SERVE / earned
  PROPOSE / not yet licensed)
- serving strip: the discipline's RESULT — live correct/refused/wrong per
  lane, wrong=0 in the verified token, with source DigestBadges
- detail (Panel + TabBar): Counts / License math / Raw. The License-math
  tab shows the honest derivation (measured ≥ θ → licensed) and states
  the numbers come from core.reliability_gate, not the workbench
- fail-closed: an empty/absent arena ledger (501 evidence_unavailable)
  renders the honest absence card pointing at the practice lane, not an
  error
- nav entry (12th) + routeConformance row + Shell nav assertion updated

Token-only (hexScan green); VirtualizedList + j/k; full vitest 398 green.
This commit is contained in:
Shay 2026-06-13 01:00:16 -07:00
parent 1fbe026209
commit 138f95a2b0
8 changed files with 530 additions and 2 deletions

View file

@ -19,6 +19,8 @@ import type {
PackDetail,
VaultSummary,
VaultEntry,
CalibrationClass,
ServingMetrics,
TurnJournalEntry,
TurnJournalSummary,
MathProposalSummary,
@ -260,3 +262,13 @@ export async function fetchVaultEntries(limit?: number, offset?: number): Promis
);
return envelope.items;
}
export async function fetchCalibrationClasses(): Promise<CalibrationClass[]> {
const envelope = await apiFetch<ItemsEnvelope<CalibrationClass>>("/calibration/classes");
return envelope.items;
}
export async function fetchServingMetrics(): Promise<ServingMetrics[]> {
const envelope = await apiFetch<ItemsEnvelope<ServingMetrics>>("/serving/metrics");
return envelope.items;
}

View file

@ -22,6 +22,8 @@ import {
fetchPack,
fetchVaultSummary,
fetchVaultEntries,
fetchCalibrationClasses,
fetchServingMetrics,
fetchTraceTurn,
fetchTraceTurns,
fetchMathProposals,
@ -47,6 +49,8 @@ import type {
PackDetail,
VaultSummary,
VaultEntry,
CalibrationClass,
ServingMetrics,
TurnJournalEntry,
TurnJournalSummary,
EvalLaneSummary,
@ -345,3 +349,23 @@ export function useVaultEntries(enabled: boolean, limit?: number, offset?: numbe
refetchOnWindowFocus: false,
});
}
export function useCalibrationClasses() {
return useQuery<CalibrationClass[], WorkbenchApiError>({
queryKey: ["api", "calibration", "classes"],
queryFn: () => fetchCalibrationClasses(),
retry: false,
staleTime: 30_000,
refetchOnWindowFocus: false,
});
}
export function useServingMetrics() {
return useQuery<ServingMetrics[], WorkbenchApiError>({
queryKey: ["api", "serving", "metrics"],
queryFn: () => fetchServingMetrics(),
retry: false,
staleTime: 30_000,
refetchOnWindowFocus: false,
});
}

View file

@ -13,6 +13,7 @@ import { EvalsRoute } from "./evals/EvalsRoute";
import { RunsRoute } from "./runs/RunsRoute";
import { PacksRoute } from "./packs/PacksRoute";
import { VaultRoute } from "./vault/VaultRoute";
import { CalibrationRoute } from "./calibration/CalibrationRoute";
import { SettingsRoute } from "./settings/SettingsRoute";
import { getWorkbenchPrefs } from "./workbenchPrefs";
@ -32,6 +33,7 @@ export function App() {
<Route path="runs/:sessionId?" element={<RunsRoute />} />
<Route path="packs/:packId?" element={<PacksRoute />} />
<Route path="vault" element={<VaultRoute />} />
<Route path="calibration" element={<CalibrationRoute />} />
<Route path="audit" element={<AuditRoute />} />
<Route path="settings" element={<SettingsRoute />} />
</Route>

View file

@ -7,6 +7,7 @@ const NAV_ITEMS = [
{ label: "Demos", to: "/demos" },
{ label: "Proposals", to: "/proposals" },
{ label: "Evals", to: "/evals" },
{ label: "Calibration", to: "/calibration" },
{ label: "Runs", to: "/runs" },
{ label: "Packs", to: "/packs" },
{ label: "Vault", to: "/vault" },

View file

@ -76,11 +76,11 @@ describe("Shell", () => {
expect(document.querySelector('[data-region="statusfooter"]')).toBeInTheDocument();
});
it("LeftNav has exactly 11 items in order", () => {
it("LeftNav has exactly 12 items in order", () => {
renderShell();
const nav = document.querySelector('[data-region="leftnav"]')!;
const links = nav.querySelectorAll("a");
expect(links).toHaveLength(11);
expect(links).toHaveLength(12);
const labels = Array.from(links).map((l) => l.textContent);
expect(labels).toEqual([
"Chat",
@ -89,6 +89,7 @@ describe("Shell", () => {
"Demos",
"Proposals",
"Evals",
"Calibration",
"Runs",
"Packs",
"Vault",

View file

@ -0,0 +1,161 @@
import { QueryClientProvider } from "@tanstack/react-query";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MemoryRouter } from "react-router-dom";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { createTestQueryClient } from "../../test/createTestQueryClient";
import type { CalibrationClass, ServingMetrics } from "../../types/api";
import { CalibrationRoute } from "./CalibrationRoute";
const classes: CalibrationClass[] = [
{
class_name: "unearned",
correct: 0,
wrong: 0,
refused: 9,
committed: 0,
reliability_floor: 0.0,
coverage: 0.0,
propose_required: 0.85,
propose_licensed: false,
serve_required: 0.99,
serve_licensed: false,
},
{
class_name: "additive",
correct: 95,
wrong: 5,
refused: 50,
committed: 100,
reliability_floor: 0.860842,
coverage: 0.66,
propose_required: 0.85,
propose_licensed: true,
serve_required: 0.99,
serve_licensed: false,
},
];
const metrics: ServingMetrics[] = [
{
lane: "train_sample",
correct: 4,
refused: 46,
wrong: 0,
sample_count: 50,
source_path: "evals/gsm8k_math/train_sample/v1/report.json",
source_digest: "sha256:aaaaaaaaaaaaaaaa",
},
];
function renderRoute() {
return render(
<QueryClientProvider client={createTestQueryClient()}>
<MemoryRouter initialEntries={["/calibration"]}>
<CalibrationRoute />
</MemoryRouter>
</QueryClientProvider>,
);
}
function okBody(data: unknown) {
return { ok: true, generated_at: "now", data };
}
function stub({ classesAvailable = true }: { classesAvailable?: boolean } = {}) {
vi.stubGlobal(
"fetch",
vi.fn((input: unknown) => {
const path = new URL(String(input)).pathname;
if (path === "/calibration/classes") {
return classesAvailable
? Promise.resolve({ json: () => Promise.resolve(okBody({ items: classes })) })
: Promise.resolve({
json: () =>
Promise.resolve({
ok: false,
generated_at: "now",
error: { code: "evidence_unavailable", message: "no practice report" },
}),
});
}
if (path === "/serving/metrics") {
return Promise.resolve({ json: () => Promise.resolve(okBody({ items: metrics })) });
}
return Promise.resolve({
json: () =>
Promise.resolve({ ok: false, generated_at: "now", error: { code: "not_found", message: path } }),
});
}),
);
}
const offsetDescriptors = {
offsetHeight: Object.getOwnPropertyDescriptor(HTMLElement.prototype, "offsetHeight"),
offsetWidth: Object.getOwnPropertyDescriptor(HTMLElement.prototype, "offsetWidth"),
};
describe("CalibrationRoute", () => {
beforeEach(() => {
Object.defineProperty(HTMLElement.prototype, "offsetHeight", { configurable: true, get: () => 560 });
Object.defineProperty(HTMLElement.prototype, "offsetWidth", { configurable: true, get: () => 520 });
});
afterEach(() => {
if (offsetDescriptors.offsetHeight) {
Object.defineProperty(HTMLElement.prototype, "offsetHeight", offsetDescriptors.offsetHeight);
}
if (offsetDescriptors.offsetWidth) {
Object.defineProperty(HTMLElement.prototype, "offsetWidth", offsetDescriptors.offsetWidth);
}
vi.restoreAllMocks();
localStorage.clear();
});
it("renders the gold-tether classes with their earned verdicts", async () => {
stub();
renderRoute();
expect(await screen.findByText("additive")).toBeInTheDocument();
expect(screen.getByText("unearned")).toBeInTheDocument();
expect(screen.getByText("earned PROPOSE")).toBeInTheDocument();
expect(screen.getByText("not yet licensed")).toBeInTheDocument();
});
it("surfaces the live serving outcome with wrong=0", async () => {
stub();
renderRoute();
expect(await screen.findByText("train_sample")).toBeInTheDocument();
// the discipline's result is present
expect(screen.getByText("Live serving outcome — the discipline's result")).toBeInTheDocument();
expect(screen.getAllByText("0 wrong").length).toBeGreaterThan(0);
});
it("shows the honest license math (measured vs θ) for a selected class", async () => {
stub();
const user = userEvent.setup();
renderRoute();
await user.click(await screen.findByText("additive"));
await user.click(screen.getByRole("tab", { name: "License math" }));
// PROPOSE licensed (>= 0.85), SERVE not (< 0.99)
expect(screen.getAllByText(/licensed/).length).toBeGreaterThan(0);
expect(screen.getByText(/core\.reliability_gate/)).toBeInTheDocument();
});
it("fail-closed: an empty arena ledger renders the honest absence card, not an error", async () => {
stub({ classesAvailable: false });
renderRoute();
expect(await screen.findByText(/No calibration evidence yet\./)).toBeInTheDocument();
expect(screen.queryByText("What failed")).not.toBeInTheDocument();
});
it("moves the class list focus with j/k through the VirtualizedList spine", async () => {
stub();
const user = userEvent.setup();
renderRoute();
const list = await screen.findByRole("listbox", { name: "Calibration classes" });
list.focus();
expect(screen.getAllByRole("option")[0]).toHaveAttribute("aria-selected", "true");
await user.keyboard("j");
expect(screen.getAllByRole("option")[1]).toHaveAttribute("aria-selected", "true");
});
});

View file

@ -0,0 +1,315 @@
import { useMemo, useState } from "react";
import { WorkbenchApiError } from "../../api/client";
import { useCalibrationClasses, useServingMetrics } from "../../api/queries";
import { DigestBadge } from "../../design/components/DigestBadge/DigestBadge";
import { MetadataTable } from "../../design/components/MetadataTable/MetadataTable";
import { Panel } from "../../design/components/Panel/Panel";
import { SearchInput } from "../../design/components/SearchInput/SearchInput";
import { SplitPane } from "../../design/components/SplitPane/SplitPane";
import { StableJsonViewer } from "../../design/components/StableJsonViewer";
import { TabBar, type Tab } from "../../design/components/TabBar/TabBar";
import { VirtualizedList } from "../../design/components/VirtualizedList/VirtualizedList";
import { EmptyState } from "../../design/components/states/EmptyState";
import { ErrorState } from "../../design/components/states/ErrorState";
import { LoadingState } from "../../design/components/states/LoadingState";
import type { CalibrationClass, ServingMetrics } from "../../types/api";
const DETAIL_TABS: readonly Tab[] = [
{ id: "counts", label: "Counts" },
{ id: "license", label: "License math" },
{ id: "raw", label: "Raw" },
];
// Sealed practice is opt-in evidence; absence is honest, not an error.
const FAIL_CLOSED_STATEMENT =
"No calibration evidence yet. The per-class arena ledger is populated by the sealed practice lane (ADR-0175).";
const FAIL_CLOSED_ACTION = "core eval math-contemplation";
function errorMessage(error: unknown) {
return error instanceof WorkbenchApiError ? error.message : "Calibration request failed.";
}
function pct(value: number): string {
return `${(value * 100).toFixed(1)}%`;
}
function verdict(c: CalibrationClass): { label: string; tone: "serve" | "propose" | "none" } {
if (c.serve_licensed) return { label: "earned SERVE", tone: "serve" };
if (c.propose_licensed) return { label: "earned PROPOSE", tone: "propose" };
return { label: "not yet licensed", tone: "none" };
}
function VerdictPill({ c }: { c: CalibrationClass }) {
const v = verdict(c);
const cls =
v.tone === "serve"
? "border-[var(--color-state-verified)] text-[var(--color-state-verified)]"
: v.tone === "propose"
? "border-[var(--color-state-warning-text)] text-[var(--color-state-warning-text)]"
: "border-[var(--color-border-subtle)] text-[var(--color-text-muted)]";
return (
<span className={`inline-flex h-6 items-center rounded-md border px-2 text-xs ${cls}`}>
{v.label}
</span>
);
}
// reliability_floor as a fill, with the two θ thresholds marked. A class
// "earns the right to guess" when its fill crosses the marker.
function ReliabilityBar({ c }: { c: CalibrationClass }) {
return (
<div
className="relative h-2 w-full overflow-hidden rounded-full bg-[var(--color-surface-inset)]"
role="img"
aria-label={`reliability ${pct(c.reliability_floor)}, PROPOSE θ ${pct(
c.propose_required,
)}, SERVE θ ${pct(c.serve_required)}`}
>
<div
className="absolute inset-y-0 left-0 rounded-full bg-[var(--color-state-verified)]"
style={{ width: pct(Math.max(0, Math.min(1, c.reliability_floor))) }}
/>
<div
className="absolute inset-y-0 w-px bg-[var(--color-text-secondary)]"
style={{ left: pct(c.propose_required) }}
/>
<div
className="absolute inset-y-0 w-px bg-[var(--color-text-primary)]"
style={{ left: pct(c.serve_required) }}
/>
</div>
);
}
function ClassRow({
c,
selected,
focused,
onSelect,
}: {
c: CalibrationClass;
selected: boolean;
focused: boolean;
onSelect: () => void;
}) {
return (
<div
role="button"
tabIndex={-1}
aria-current={selected ? "true" : undefined}
onClick={onSelect}
className={`grid w-full gap-2 border-b border-[var(--color-border-subtle)] px-3 py-2 text-left transition-colors hover:bg-[var(--color-surface-inset)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-inset focus-visible:outline-[var(--color-focus-ring)] ${
selected ? "bg-[var(--color-selected-bg)]" : ""
} ${
selected
? "border-l-2 border-l-[var(--color-selected-border)] pl-[10px]"
: focused
? "border-l-2 border-l-[var(--color-focus-ring)] pl-[10px]"
: "border-l-2 border-l-transparent pl-[10px]"
}`}
>
<span className="flex items-center justify-between gap-2">
<span className="font-mono text-sm text-[var(--color-text-primary)]">{c.class_name}</span>
<VerdictPill c={c} />
</span>
<ReliabilityBar c={c} />
<span className="flex items-center gap-3 text-xs tabular-nums">
<span className="text-[var(--color-text-secondary)]">
reliability {pct(c.reliability_floor)} · committed {c.committed}
</span>
<span className="text-[var(--color-text-muted)]">{c.correct} correct</span>
<span className="text-[var(--color-text-muted)]">{c.refused} refused</span>
<span
className={
c.wrong > 0
? "text-[var(--color-state-contradicted)]"
: "text-[var(--color-text-muted)]"
}
>
{c.wrong} wrong
</span>
</span>
</div>
);
}
function ServingStrip({ metrics }: { metrics: ServingMetrics[] }) {
return (
<section className="grid gap-2 rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-surface-inset)] p-3">
<h3 className="m-0 text-xs font-semibold text-[var(--color-text-secondary)]">
Live serving outcome the discipline's result
</h3>
<div className="grid gap-1">
{metrics.map((m) => (
<div key={m.lane} className="flex items-center gap-3 text-xs tabular-nums">
<span className="font-mono text-[var(--color-text-primary)]">{m.lane}</span>
<span className="text-[var(--color-text-muted)]">{m.correct} correct</span>
<span className="text-[var(--color-text-muted)]">{m.refused} refused</span>
<span
className={
m.wrong > 0
? "font-semibold text-[var(--color-state-contradicted)]"
: "font-semibold text-[var(--color-state-verified)]"
}
>
{m.wrong} wrong
</span>
</div>
))}
</div>
</section>
);
}
function LicenseMath({ c }: { c: CalibrationClass }) {
const row = (action: string, required: number, licensed: boolean) => ({
key: action,
value: (
<span className="tabular-nums">
measured {pct(c.reliability_floor)} {licensed ? "≥" : "<"} θ {pct(required)} {" "}
<span
className={
licensed
? "text-[var(--color-state-verified)]"
: "text-[var(--color-text-muted)]"
}
>
{licensed ? "licensed" : "not licensed"}
</span>
</span>
),
});
return (
<div className="grid gap-3">
<p className="m-0 text-xs text-[var(--color-text-muted)]">
Reliability is the engine's one-sided Wilson conservative floor on commitment precision
(correct / committed), and is 0 below N_MIN=10 committed trials. A class is licensed for an
action when its measured reliability clears that action's θ. The workbench computes none of
this it is read from <span className="font-mono">core.reliability_gate</span>.
</p>
<MetadataTable
rows={[
{ key: "committed (N)", value: String(c.committed), mono: true },
{ key: "reliability floor", value: pct(c.reliability_floor), mono: true },
row("PROPOSE", c.propose_required, c.propose_licensed),
row("SERVE", c.serve_required, c.serve_licensed),
]}
/>
</div>
);
}
function ClassDetail({ c }: { c: CalibrationClass }) {
const [tab, setTab] = useState("counts");
return (
<Panel title={c.class_name} toolbar={<VerdictPill c={c} />}>
<TabBar tabs={DETAIL_TABS} activeTab={tab} onTabChange={setTab}>
{tab === "counts" ? (
<MetadataTable
rows={[
{ key: "correct", value: String(c.correct), mono: true },
{ key: "wrong", value: String(c.wrong), mono: true },
{ key: "refused", value: String(c.refused), mono: true },
{ key: "committed", value: String(c.committed), mono: true },
{ key: "coverage", value: pct(c.coverage), mono: true },
]}
/>
) : null}
{tab === "license" ? <LicenseMath c={c} /> : null}
{tab === "raw" ? <StableJsonViewer source={JSON.stringify(c, null, 2)} /> : null}
</TabBar>
</Panel>
);
}
export function CalibrationRoute() {
const [search, setSearch] = useState("");
const [selected, setSelected] = useState<string | null>(null);
const classesQuery = useCalibrationClasses();
const metricsQuery = useServingMetrics();
const classes = classesQuery.data ?? [];
const filtered = useMemo(() => {
const q = search.trim().toLowerCase();
if (!q) return classes;
return classes.filter((c) => c.class_name.toLowerCase().includes(q));
}, [search, classes]);
const selectedClass = classes.find((c) => c.class_name === selected) ?? null;
if (classesQuery.isLoading) {
return <LoadingState label="Loading calibration..." />;
}
if (classesQuery.isError) {
if (classesQuery.error.code === "evidence_unavailable") {
return <EmptyState statement={FAIL_CLOSED_STATEMENT} nextAction={{ kind: "cli", command: FAIL_CLOSED_ACTION }} />;
}
return (
<ErrorState
whatFailed={errorMessage(classesQuery.error)}
mutationStatus="No calibration mutation occurred."
reproducer="curl /calibration/classes"
retrySafety="Retry: safe"
/>
);
}
if (classes.length === 0) {
return <EmptyState statement={FAIL_CLOSED_STATEMENT} nextAction={{ kind: "cli", command: FAIL_CLOSED_ACTION }} />;
}
return (
<div className="h-full min-h-0">
<SplitPane direction="horizontal" id="calibration" defaultSplit={44} minSize={340}>
<Panel title="Gold-tether classes">
<div className="grid min-h-0 gap-3">
{metricsQuery.data && metricsQuery.data.length > 0 ? (
<ServingStrip metrics={metricsQuery.data} />
) : null}
<SearchInput placeholder="Filter by class" value={search} onChange={setSearch} />
<VirtualizedList
ariaLabel="Calibration classes"
estimateSize={92}
getKey={(c) => c.class_name}
height="calc(100vh - 20rem)"
initialRect={{ width: 520, height: 560 }}
items={filtered}
onActivate={(c) => setSelected(c.class_name)}
renderItem={(c, _index, focused) => (
<ClassRow
c={c}
selected={c.class_name === selected}
focused={focused}
onSelect={() => setSelected(c.class_name)}
/>
)}
/>
</div>
</Panel>
<section className="h-full min-h-0 overflow-y-auto pl-3">
{selectedClass ? (
<ClassDetail c={selectedClass} />
) : (
<EmptyState
statement="Select a class to see how it earns — or doesn't earn — the right to guess."
nextAction={{ kind: "cli", command: FAIL_CLOSED_ACTION }}
/>
)}
{metricsQuery.data && metricsQuery.data.length > 0 ? (
<div className="mt-3 grid gap-1 px-1 text-xs text-[var(--color-text-muted)]">
{metricsQuery.data.map((m) => (
<span key={`src-${m.lane}`} className="flex items-center gap-2">
{m.lane} source
<DigestBadge digest={m.source_digest.replace(/^sha256:/, "")} truncate={12} />
</span>
))}
</div>
) : null}
</section>
</SplitPane>
</div>
);
}

View file

@ -16,6 +16,7 @@ import { DemoTheaterRoute } from "./demos/DemoTheaterRoute";
import { RunsRoute } from "./runs/RunsRoute";
import { PacksRoute } from "./packs/PacksRoute";
import { VaultRoute } from "./vault/VaultRoute";
import { CalibrationRoute } from "./calibration/CalibrationRoute";
import { SettingsRoute } from "./settings/SettingsRoute";
/**
@ -194,6 +195,17 @@ const MOUNT_ROUTES: MountRouteSpec[] = [
"No persisted vault. Session memory is held in-process and discarded on exit; persistence is opt-in via RuntimeConfig.persist_session_state.",
emptyCommand: "Set RuntimeConfig.persist_session_state = true",
},
{
name: "Calibration",
element: <CalibrationRoute />,
path: "/calibration",
initialEntry: "/calibration",
loadingLabel: "Loading calibration...",
// Fail-closed: an empty arena ledger is the honest primary state.
emptyStatement:
"No calibration evidence yet. The per-class arena ledger is populated by the sealed practice lane (ADR-0175).",
emptyCommand: "core eval math-contemplation",
},
];
describe.each(MOUNT_ROUTES)("route conformance: $name", (spec) => {