The New Guard · Labs · August 2026 · Companion to Issue #027

Two files. Same underlying model. One prompt: build a playable SkiFree clone in a single HTML file. One of them opens to a polished title screen, a chasing yeti, a working game. The other paints one gorgeous frame and then freezes the browser tab so hard it blocks its own navigation. The only difference between the two models is a safety edit: the second one had its refusals surgically removed. It also, it turns out, had its second thoughts removed.

This is the hands-on companion to this week’s issue, where the theme was safety controls shipping with a bypass. Here is what one bypass actually cost, measured on a desk.

🧪 The Setup

One RTX 5090, 32 GB, running four open-weight 30B-class models through a single local llama.cpp stack on localhost:8090. No API spend, no cloud. The contestants:

  • Qwen3.8-27B (the Apache-2.0 dense model Issue #027 covered), our current daily driver, served at Q5_K_M.
  • Qwen3.8-27B abliterated (huihui-ai’s decensored build), the same base weights with refusal directions removed, served at Q4_K.
  • Muse Glimmer 30B (a reasoning model), included as a strong control.
  • Qwen3-Coder-30B, the older coding specialist, as a fourth data point.

Every model got the identical prompt: a single self-contained HTML file, all CSS and JS inline, implementing the classic Windows SkiFree, including the iconic yeti that chases you down and eats you. One shot. No iteration, no test feedback, no repair loop. Whatever the model wrote the first time is what we graded.

The base Qwen3.8-27B SkiFree title screen: a SKIFREE logo over THE ETERNAL SLOPE, snow-covered pines, and a skier leaving twin tracks.

The base model's title screen. It plays.

Then we did the boring, important part: we actually ran all four in a real browser, watched the console, and drove them with real keypresses. Structural completeness is easy to fake. “It boots and renders without throwing” is not.

📊 The Scoreboard

ModelBootsConsole errorsObstacles renderResult
Qwen3.8-27B (daily)Yes, polished title screenNoneYesWorks. Best of the four.
Qwen3-Coder-30BYes, plainNoneYes, scroll correctlyWorks. Mechanically sound.
Muse Glimmer 30BYesNoneNo (renders desynced)Runs, core mechanic broken
Qwen3.8 abliteratedFor one frame(renderer hung)Never gets thereHard fail. Freezes the browser.
Qwen3-Coder's SkiFree in play: a bordered white slope, a red-and-blue skier, and a green pine obstacle scrolling down toward it, with a distance and speed HUD.

Qwen3-Coder's game: plain, but the obstacles actually spawn and scroll into you.

The daily driver produced a genuine little game: a title screen reading “THE ETERNAL SLOPE,” a HUD with speed and best-run tracking, a sound toggle, a pause key, and a yeti tuned to warn you at 380 meters, spawn at 450, and then outrun you by design. Zero console errors. Qwen3-Coder wrote a plainer game but a correct one, with obstacles that actually spawn at the top and scroll down into you. Muse Glimmer runs but applies its camera transform to obstacles twice, so they scroll at double speed and desync from their own collision boxes: playable, but the dodging is visually broken.

And the abliterated model froze the tab.

🧊 The Prettiest Frame

Here is the twist worth sitting with. Before it locked, the abliterated build was the most visually appealing of the four. Its title screen is the richest: an animated ambient snowfield, a glowing beveled frame around the canvas, hand-drawn gradient sprites, a detailed yeti with fur strokes and a bobbing gait. It packed more visual craft per byte than any other entry.

The abliterated Qwen3.8 SkiFree title screen: a gilded SKI FREE logo, an ABOMINABLE INTERSTATE tagline, a framed instruction panel, and detailed pine borders down both sides.

The abliterated model's title screen: the richest of the four. This frame is the last one it ever draws. (Captured from a copy with the freeze loop disabled, since the live build locks the tab before a screenshot can land.)

Then it never painted a second frame.

The cause is a single loop, and it is the same shape in two places:

while (world.wall.some(w => w.y > H+40)) spawnWall(H + rand(0,30));

The intent is “keep spawning boundary trees until the bottom of the slope is filled.” But the exit condition and the loop body contradict each other. The loop runs while any wall sits below the line at y = 760. The body spawns new walls above that line, at y around 720 to 750, which never satisfy the condition. Nothing in the loop removes the wall that is triggering it. The world seeds boundary walls all the way down to y = 766 on startup, so the instant the loop runs, the condition is permanently true. It spawns walls forever, the main thread never yields, and the renderer locks.

Its correct sibling sits one line above it:

while (world.wall.length && world.wall[0].y < -50) world.wall.shift();

Same shape, but it removes from the front, so it terminates. The bug is the exact same loop with push where it needed shift, plus a condition the producer can never clear.

Why it renders one beautiful frame first: the game uses a fixed-timestep accumulator. On the very first animation frame, elapsed time is near zero, so the update step is skipped and only the render runs, painting that lush seeded title screen. On the next frame the accumulator crosses one-sixtieth of a second, the update runs for the first time, hits the loop, and the tab hangs before it can paint frame two. The most beautiful version of the game is also the one that could not survive its own first tick.

🔤 Same Weights, Two Different Authors

We read both games line by line. The base model and its abliterated twin do not just differ in correctness. They write in visibly different voices.

Qwen3.8 base writes like a careful engineer building something to maintain:

  • It uses real HTML and CSS for the HUD, the title, the game-over and pause screens, and reserves the canvas for the game field alone.
  • It names every tunable: MPP = 0.15 with the comment meters per world pixel, WARN_M = 380, SPAWN_M = 450 with the comment yeti appears (meters), BEST_KEY = 'skifree.best.v1'.
  • Its identifiers are descriptive and column-aligned. Its functions have line breaks and explanatory comments.

The abliterated model writes like a demoscene one-file compression:

  • Everything is drawn on the canvas, including the HUD and every overlay. There is no DOM UI at all.
  • Names collapse to single characters: cv, ctx, g, p, y, w, o, q. Statements pack five to a line. Magic numbers sit inline everywhere, including the H+40 and H+70 at the heart of the bug.
  • Section-banner comments only. No prose explaining intent.

Both files are around 40 KB and both hand-roll audio synthesis, particle systems, and a detailed yeti. The abliterated one is arguably denser: it spends more of its bytes on visual richness and none on readability.

The tell that ties the voice to the bug: on the identical prompt, the base model produced roughly 115,000 characters of chain-of-thought before it wrote a line of code (on the order of 28,000 tokens). The abliterated model produced 4,300, about a twenty-sixth as much. Same weights, an order of magnitude and a half less thinking before committing to code. It wrote more, faster, prettier, and shipped a loop that ten seconds of reading, or one glance at the working shift loop directly above it, would have caught.

🧠 What Abliteration Actually Removed

Abliteration removes a model’s ability to refuse by identifying the direction in activation space that corresponds to refusal and editing it out. On the safety axis, this build works exactly as advertised, and we measured it two ways.

On a graded refusal battery, the base Qwen3.8 refused two of eight prompts, the two that were genuinely harmful. The abliterated model refused zero. The safety layer came off cleanly, and only where it mattered: the base model was already permissive on the dual-use and edgy-creative prompts, so those were never the difference.

On capability, the decensoring looked free. Both models scored 25 out of 25 on our standard reasoning-and-coding suite, with near-identical token counts and speed. On the harder aider polyglot benchmark, both landed at 76.5% pass rate, dead even. By every number a benchmark produces, abliterating this model cost nothing. (One caveat we will not hide: the base ran at Q5_K_M and the abliterated at Q4_K, so quantization is a second uncontrolled variable here. But the capability scores stayed identical across both that gap and the abliteration, which if anything sharpens the point below: the benchmarks were not measuring the thing that broke.)

Then we asked it to build a whole thing, and the story changed. The refusal edit appears to have come with a side effect the benchmarks never probed: the model stopped thinking out loud. The deliberation that a reasoning model uses to catch its own mistakes is exactly the kind of behavior that lives in the same activation space you are editing when you remove refusals. Cut hard enough to remove the “I won’t,” and you may also dull the “wait, let me check that loop.”

We are careful here, because The New Guard’s whole premise is measured, not vibed: this is one prompt, one sample per model, at the model-card temperature. It is a strong signal, not a proof. But it is a signal the standard benchmarks are structurally blind to, because a 25-out-of-25 suite and a polyglot pass rate both measure whether short, self-contained answers are correct. Neither measures whether a model can hold a whole interactive system in its head without shipping a fatal loop. A real build did in one shot what two benchmark suites missed entirely.

🔧 What Builders Should Take From This

Uncensored is not free, and “passes the benchmarks” is not “safe to ship.” The abliterated Qwen3.8 is, by every capability number we could produce, indistinguishable from the model it was cut from. It still froze the browser on the first real task we gave it. If you are reaching for a decensored open model because the benchmarks say it is a clean swap, run it on the actual shape of your work before you trust that. Short-answer benchmarks and whole-system builds are different tests, and the gap between them is where the cost of the bypass showed up.

When you measure a model, make one of your tests a real thing it has to hold together. The polyglot suite is a fine discriminator and we use it. It also completely missed the difference that mattered here. One atomic, buildable task, graded by actually running it, told us more about production readiness than two clean benchmark sweeps did.

And the thematic point, since this rides with an issue about brake pedals and bypasses: the brake came off exactly as designed. What nobody advertised is that the same cut may have taken the model’s second thoughts with it. The base model kept its refusals and its habit of checking its own work. Its uncensored twin lost both.

🧾 Reproduction

Every game is a single self-contained HTML file. All four, the generator, and the measured data live on the bench. The generator sends one identical prompt per model through the local llama-swap stack, extracts the HTML, and writes one file per model. The abliterated freeze reproduces on load, in any modern browser, within about a second of the world beginning to scroll. The two working games (the base Qwen3.8 build and the Qwen3-Coder build) are playable end to end, yeti included.