Files
PIG-Demo/src/content/lineup.ts
T
karti-ai 408ce4a525 Capture harness, fixture verification, CI, and the public README
The site does no live inference. Rollouts are captured once against spark-1 and
replayed at their recorded wall-clock — a public demo with no auth cannot hold
an API key, and a recorded run can be scrubbed, permalinked, blind-compared and
verified in ways a live one cannot. What stops it being a video is that the
browser re-derives every number from the recorded moves.

verify_fixtures.py is the Python half of that: it replays every committed
fixture through the engine and reproduces its own rewards. All 16 land at
delta 0.0. A fixture that cannot be regenerated is a claim with no receipt.

First real measurement, thinking off, 8 seeds: solved 0/8. The model repeats
guesses it has already played, invents words (trape, slith, postt, boomy),
and contradicts its own feedback — consistency 0.09 to 0.17. That is the
published failure taxonomy showing up in our own data on the first run, and it
is why `consistency` is a reward component rather than a footnote.

A capture failure is recorded as a turn with a null reply, never dropped. A
capture that silently discarded failed turns would be reporting a better model
than the one that ran.

CI gates both halves and four things that fail silently in production: the word
lists must rebuild byte-identically, the prerendered routes must carry their own
baked og tags (crawlers do not run JS, so without them every shared link
previews as the homepage), no blob: URL may reach the bundle (the site's CSP has
no worker-src, so it falls back to default-src 'self' and a blob worker is
blocked with no error), and the conformance digest must match across languages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019mt6sHQHEnEYrJZvoMCJSB
2026-08-28 15:47:31 -07:00

77 lines
3.0 KiB
TypeScript

/**
* The join between the demo registry and the vertical lineup.
*
* This is the ONLY place the marketing pages touch the registry. Home, Gallery
* and Vertical all read demos through here, so when the registry's export name
* or path moves, it moves in one line instead of in four pages.
*/
import { demos } from '@/lib/demo-kit/registry';
import type { DemoMeta, Vertical } from '@/lib/demo-kit/types';
import { VERTICALS, verticalByKey } from '@/content/verticals';
import type { VerticalEntry } from '@/content/verticals';
/**
* Route shapes, written down once. The router owns the actual `<Route>`
* elements; these are what every link on the marketing side builds, so if the
* two ever disagree, they disagree here and not in twenty JSX attributes.
*/
export const routes = {
home: '/',
gallery: '/gallery',
honesty: '/honesty',
demo: (slug: string) => `/demos/${slug}`,
vertical: (slug: string) => `/verticals/${slug}`,
/** Gallery pre-filtered to one vertical. Deep-linkable on purpose. */
galleryFiltered: (key: Vertical) => `/gallery?vertical=${key}`,
} as const;
/**
* The repository link belongs to the chrome, which already owns it. Re-exported
* rather than repeated so the marketing pages and the footer cannot end up
* pointing at two different repositories.
*/
export { REPO_URL } from '@/components/site/links';
/** Already sorted by `order` then slug by the registry. Never sort it again. */
export const allDemos: readonly DemoMeta[] = demos;
export const liveDemos: readonly DemoMeta[] = allDemos.filter((d) => d.status === 'live');
/**
* The demo the site leads with. `reference` is the hello-world vertical, and
* the first live one in it is the front door; if there is none yet, any live
* demo will do, and only then do we fall back to whatever the registry has.
* Written as a function of the registry so adding a demo never edits Home.
*/
export const featuredDemo: DemoMeta | undefined =
liveDemos.find((d) => d.vertical === 'reference') ?? liveDemos[0] ?? allDemos[0];
/** Every vertical key that at least one demo is filed under. Filter source. */
export const verticalKeysInUse: readonly Vertical[] = Array.from(
new Set(allDemos.map((d) => d.vertical)),
);
export function demosForVertical(key: Vertical | null): readonly DemoMeta[] {
if (!key) return [];
return allDemos.filter((d) => d.vertical === key);
}
export function demoBySlug(slug: string | undefined): DemoMeta | undefined {
if (!slug) return undefined;
return allDemos.find((d) => d.slug === slug);
}
/**
* A demo's vertical, for a label on a card. `reference` deliberately resolves
* to nothing — the word game is not an industry, and labelling it as one would
* be the first small lie on a site whose whole argument is that it doesn't
* tell them.
*/
export function verticalForDemo(demo: DemoMeta): VerticalEntry | undefined {
return verticalByKey(demo.vertical);
}
/** The lineup, in the order we would build it. */
export const lineup: readonly VerticalEntry[] = [...VERTICALS].sort((a, b) => a.rank - b.rank);