Frontend: site chrome, demo shell, pages, and the contract gates

Five parallel lanes plus an integration pass. The header, gallery, router and
sitemap are all generated from the demo registry, so adding src/demos/<slug>/
puts a demo everywhere with zero edits to shared files — which is the whole
reason demo nine cannot break demo one.

check-demos enforces the twelve contract rules: 142 checks over one live demo.
Two worth naming. The shell may not mention a specific slug, because an
'if (slug === wordle)' in src/components/demo/ is a contract bug wearing a
patch. And a spec-status demo must ship a real specification — task, actions,
grader, counterweight, eval command — since a coming-soon card reads worse than
an honest empty gallery.

Bundle budget holds: entry 108.79 kB gzipped against a 160 kB ceiling, the demo
chunk 21.15 kB against 90 kB. recharts is 108 kB gzipped and lives behind a lazy
import so it never touches the entry.

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 16:09:59 -07:00
parent b601511e7f
commit eb88138d15
31 changed files with 1341 additions and 680 deletions
+53
View File
@@ -0,0 +1,53 @@
"""The reward this demo quotes, as a runnable placeholder.
A real demo points `reward.source.path` at its environment package — e.g.
`envs/__package__/__package__/reward.py` — and quotes the function the grader
actually runs. This file exists so a freshly scaffolded demo has a receipt that
RESOLVES on day one: an empty receipt panel reads to a visitor as the code not
existing, which is the exact impression this site is built to avoid.
Move the region markers into the environment and repoint `source.path` as soon
as the environment lands. `scripts/check-receipts.mjs` will tell you the moment
the two disagree.
"""
from dataclasses import dataclass
@dataclass
class Episode:
"""One rollout, as the environment records it."""
escalated: frozenset[str]
needed: frozenset[str]
malformed_actions: int
# region: pig-demo/score
def score(episode: Episode) -> dict[str, float]:
"""Three terms, weighted 0.60 / 0.25 / 0.15 in the demo's RewardSpec.
`caught` is the objective. `restraint` is the counterweight: it is what
stops the objective being maximised the crude way, by escalating the whole
queue. `well_formed` is a gate — every competent policy scores 1.0 on it,
so it is declared a gate rather than dressed up as a second counterweight.
"""
needed = episode.needed
escalated = episode.escalated
caught = len(escalated & needed) / len(needed) if needed else 1.0
noise = escalated - needed
quiet = len(escalated) - len(noise)
restraint = 1.0 - (len(noise) / len(escalated)) if escalated else 1.0
well_formed = 0.0 if episode.malformed_actions else 1.0
return {
"caught": caught,
"restraint": restraint,
"well_formed": well_formed,
# Unweighted diagnostic. Rendered, never summed into the reward.
"escalations_that_landed": float(quiet),
}
# endregion: pig-demo/score