OSS hardening 4/4: CI rebuilds the widget shell and fails on drift - #73
OSS hardening 4/4: CI rebuilds the widget shell and fails on drift#73adamstankiewicz wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
0ca2a1a to
971a217
Compare
971a217 to
a5c880a
Compare
a5c880a to
d61b07c
Compare
public/widget-shell.html is a committed build artifact by necessity (next build copies public/ before mcp/build.mjs can run), and it rots silently: this commit's rebuild proves it — the committed shell predated the two newest widget kinds, so debate-ai and writing-workshop rendered 'No renderer registered' in every MCP host. The rebuild is byte-deterministic (verified: identical hashes across runs), so CI now rebuilds and diffs it after the build step, with a fix-it message when it drifts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The CI guard failed on its first real run, honestly: next/font's @font-face rules carry build-environment-specific media hashes, so the rebuild was never byte-deterministic. The rules were also dead weight — a standalone single-file shell has no ../media/, so those fonts never loaded. Stripping them fixes both: 4KB lighter, and consecutive builds are now byte-identical (verified). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
d61b07c to
627cd09
Compare
mcp/shell.css imports the app's own globals.css and owns the few things next/font would have provided (every --font-* variable gets a real fallback stack — including the serif the warm-minimal branch needs — plus host transparency). build.mjs compiles it with the Tailwind CLI instead of lifting chunks out of .next, which: - breaks the circular next-build dependency, so the shell runs as predev/prebuild and is never committed (gitignored) or manually rebuilt, - is deterministic by construction — next/font never runs here, so there is no @font-face to strip and nothing environment-dependent to guard, - single-sources theming: a retheme of globals.css lands in the shell automatically, - and drops 20KB of CSS that was never reachable. Verified: builds in ~90ms with no .next present; two consecutive builds byte-identical; zero url() references; theme tokens, dark block, and focus styles present; full pnpm build green end-to-end. Supersedes the committed-artifact staleness guard (#73's CI step) once both merge — a build product can't go stale. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Superseded by #86, unmerged on purpose: every change here existed to police the committed Nothing is lost in the trade: CI's existing 🤖 Generated with Claude Code |
mcp/shell.css imports the app's own globals.css and owns the few things next/font would have provided (every --font-* variable gets a real fallback stack — including the serif the warm-minimal branch needs — plus host transparency). build.mjs compiles it with the Tailwind CLI instead of lifting chunks out of .next, which: - breaks the circular next-build dependency, so the shell runs as predev/prebuild and is never committed (gitignored) or manually rebuilt, - is deterministic by construction — next/font never runs here, so there is no @font-face to strip and nothing environment-dependent to guard, - single-sources theming: a retheme of globals.css lands in the shell automatically, - and drops 20KB of CSS that was never reachable. Verified: builds in ~90ms with no .next present; two consecutive builds byte-identical; zero url() references; theme tokens, dark block, and focus styles present; full pnpm build green end-to-end. Supersedes the committed-artifact staleness guard (#73's CI step) once both merge — a build product can't go stale. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* experiment: does the shell survive as a post-build product? If the Vercel preview serves /widget-shell.html despite it being absent from git, output collection happens after the build command — and the committed artifact, the manual mcp:build step, and the CI staleness guard can all be deleted in favor of the build building the shell. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: the widget shell builds itself, themed from one source mcp/shell.css imports the app's own globals.css and owns the few things next/font would have provided (every --font-* variable gets a real fallback stack — including the serif the warm-minimal branch needs — plus host transparency). build.mjs compiles it with the Tailwind CLI instead of lifting chunks out of .next, which: - breaks the circular next-build dependency, so the shell runs as predev/prebuild and is never committed (gitignored) or manually rebuilt, - is deterministic by construction — next/font never runs here, so there is no @font-face to strip and nothing environment-dependent to guard, - single-sources theming: a retheme of globals.css lands in the shell automatically, - and drops 20KB of CSS that was never reachable. Verified: builds in ~90ms with no .next present; two consecutive builds byte-identical; zero url() references; theme tokens, dark block, and focus styles present; full pnpm build green end-to-end. Supersedes the committed-artifact staleness guard (#73's CI step) once both merge — a build product can't go stale. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
CI now rebuilds
public/widget-shell.htmland diffs it against the committed copy. The committed shell was stale — debate-ai and writing-workshop were silently broken in MCP hosts — which this both fixes and prevents: a registry change that forgetspnpm mcp:buildfails the build instead of failing students.Final part of the OSS hardening stack (#69 → #70 → 3/4 → this).
🤖 Generated with Claude Code