fix: compile-check svelte variants at publish time

Field failure (Codex session, 2026-07-28): the agent kept the seeded
stub style block and appended its own second top-level style element in
all three variants. Svelte forbids that, so the user saw a red Vite
compile overlay; the mount-ack loop then self-healed (failure event,
repair, republish, clean accept), but the overlay window is exactly the
kind of thing the user should never see.

The publish gate closes the class: a done reply for a component session
now compile-checks every variant with the app's own compiler BEFORE the
revision bump and the browser broadcast. Failures bounce as a 422 with
file, line, and message plus _instructions; live-poll surfaces the
details in the thrown reply error. The browser never imports a variant
that cannot compile.

Also: the stub guard comments warn that all CSS belongs in the single
existing style block, worded to never contain the literal "<style"
sequence (a mention inside a CSS comment truncates the string surgery
agents use to find the block; the fake test agent caught exactly that).
The JIT svelte instructions carry the same warning.

This work was produced with AI assistance (Claude Code).

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-07-28 14:13:47 -07:00
co-authored by Claude Code
parent da68678e7e
commit dc5420b64f
5 changed files with 131 additions and 5 deletions
+16
View File
@@ -55,6 +55,7 @@ import {
import {
applyDeferredSvelteComponentAccepts,
bumpSvelteComponentPreviewRevision,
compileCheckVariants,
removeAllSvelteComponentSessions,
sweepInactiveSvelteComponentSessions,
} from './live/svelte-component.mjs';
@@ -1322,9 +1323,24 @@ function handlePollPost(req, res) {
// variant files into a fresh revision dir before the browser is told:
// the import path changes every publish, so no transform cache can pin a
// stale compile of a republished module (node_modules is unwatched).
// Broken variants are bounced HERE, before the browser imports anything:
// a compile error that reaches the page is a red overlay in the user's
// face; bounced at publish it is a private fix with file and line.
if (replyFileMeta.previewMode === 'svelte-component'
&& msg.id
&& (msg.type === 'done' || !msg.type)) {
let compileCheck = { ok: true, failures: [] };
try { compileCheck = compileCheckVariants(msg.id, process.cwd()); } catch { /* best-effort */ }
if (!compileCheck.ok) {
res.writeHead(422, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
error: 'variant_compile_failed',
id: msg.id,
failures: compileCheck.failures,
_instructions: 'The publish was NOT delivered: the listed variant file(s) do not compile, so the browser never saw them. Fix each failure at the given file and line (the most common cause is a second top-level <style> element; Svelte allows exactly one, so merge all rules into the existing block), then send the same --reply done again.',
}));
return;
}
try { bumpSvelteComponentPreviewRevision(msg.id, process.cwd()); } catch { /* best-effort */ }
}
if (state.sessionStore && msg.id && !skipJournalReply) {