The StormWatch incident made the problem concrete. The planner asked the worker to generate CSS for a weather dashboard. The worker produced clean CSS — selectors, properties, values. The planner patched it into the HTML file. The result was literal CSS text rendering in the browser, because nobody wrapped it in <style> tags.

This is a category of bug that doesn’t happen in human development. A person writing CSS for an HTML file instinctively wraps it in a style block. But the pipeline has a separation between generation and placement. The worker generates content. The planner decides where it goes. file_patch inserts it. If the planner doesn’t specify wrapper tags and the worker doesn’t include them, raw CSS text appears in the HTML document.

The cross-language detector catches three main patterns. CSS in HTML: selector-block patterns (div { color: red }) appearing outside <style> tags. JavaScript in HTML: function declarations, variable assignments, and control flow statements outside <script> tags. And the reverse confusion: .css files containing <style> wrapper tags, or .js files containing <script> tags — the LLM treating standalone files as if they were HTML fragments.

The detection uses a regex state machine that tracks protected zones. Content inside legitimate <style> and <script> blocks is excluded from detection. Everything outside those zones is scanned. A two-line minimum threshold prevents false positives from stray text that happens to look like code — a sentence containing the word function in an HTML comment shouldn’t trigger a repair.

Repair is straightforward when detection fires. Unwrapped CSS gets wrapped in <style> tags. Unwrapped JavaScript gets wrapped in <script> tags. Redundant wrapper tags in standalone files get stripped. The repairs are conservative — better to miss an edge case than to corrupt a file with a false positive.

The detector runs at two points in the pipeline. First, on fragments — the generated code from the worker, before it’s patched into the target file. This catches the StormWatch pattern early. Second, on the full file after patching — defence in depth, catching cases where the fragment was clean but the insertion point created a cross-language boundary. The code fixer also gained a structural integrity validation step that runs after all language-specific fixers, checking that the file’s overall structure is still valid.

It’s a band-aid on a deeper problem. The real fix would be for the planner to always specify the correct wrapper context when directing cross-language insertions. But planner prompts can only do so much — the planner is an LLM, and LLMs occasionally forget instructions. The detector catches what the planner misses. Practical reliability over theoretical correctness.