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
This commit is contained in:
karti-ai
2026-08-28 15:47:31 -07:00
parent 69607fbfe9
commit 408ce4a525
43 changed files with 5279 additions and 136 deletions
+9 -7
View File
@@ -6,7 +6,7 @@
* or path moves, it moves in one line instead of in four pages.
*/
import { demos } from '@/lib/demo-kit';
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';
@@ -26,13 +26,15 @@ export const routes = {
galleryFiltered: (key: Vertical) => `/gallery?vertical=${key}`,
} as const;
/** The public repository. Every claim on the site is meant to end up here. */
export const REPO_URL = 'https://github.com/karti-ai/PIG-Demo';
/**
* 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';
/** Registry order is authorial; this is the order every list renders in. */
export const allDemos: readonly DemoMeta[] = [...demos].sort(
(a, b) => a.order - b.order || a.slug.localeCompare(b.slug),
);
/** 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');