Solar System — how it was built

The smooth one — and why it was the spec that made it smooth.

Built by Huginn: Kai writes the spec, Huginn writes the code — one small checkpoint at a time against a hard gate. Two versions, one spec: one ran on a small local model (Qwen3.6-27B, INT4), one on a cloud model (DeepSeek). Both in Three.js.

The honest part

This is the counterweight to Pac-Man. Where Pac-Man churned, the solar system came together almost in one shot — and the difference was the spec, not the model. Every one of the eight checkpoints was specified in tight detail and, crucially, shipped with a test that asserted real behaviour, not just "it compiled."

The only round of changes was cosmetic, after a human looked at it: the scene was too dark, Saturn's ring span the wrong way, and everything orbited clockwise instead of counter-clockwise. Real things — but a single polish pass (checkpoint 08) folded them all in. Eight checkpoints and one polish pass, versus Pac-Man's thirteen. Same harness, the same local-vs-cloud model split. What differed was how much the spec pinned down before the first line of code, and whether the gate tested behaviour or just compilation.

How do you let a model build something it can't see?

A 3D scene is invisible to a headless agent — and to the gate. So the page exposes a small inspection hook, window.__solar: bodyPosition(name), pickAt(x,y), stepFrames(n), bodies, asteroidCount. The test harness drives the real scene through it and asserts true facts — "after stepFrames(120) Earth's position changed", "pickAt over Mars returns Mars", "orbits run counter-clockwise" — no screenshots, no eyeballing. That hook is what made a 3D scene buildable by a model that never saw a single frame.

The instructions we handed Huginn

A settled design doc, an operating manual (AGENTS.md), and a non-negotiable per-checkpoint gate:

Do exactly one checkpoint per turn, then stop.
Before every commit, the gate must be green:
  • eslint                 — clean, zero warnings
  • node test/smoke.mjs    — headless Chromium (software WebGL) loads the page,
                             waits for window.__solar.ready, and asserts THIS
                             checkpoint's behaviour, with zero console errors
  • commit on the build branch, never push, then summarize and stop

And the kickoff that drove the whole build (verbatim, paths trimmed):

Push-through run. Implement checkpoints CP01 through CP08 in order, one at a
time. For each: read the checkpoint spec, implement only that checkpoint, run
the gate (eslint clean, then node test/smoke.mjs prints SMOKE OK), fix until
green, commit on the build branch, then proceed to the next. Stop when CP08
is green, or stop early and summarize if blocked.

The spec — checkpoint by checkpoint

  1. Foundation — renderer, camera + orbit controls, starfield, a placeholder sun, the window.__solar hook, and the smoke-test gate.
  2. Planets — the eight planets from a data table, orbit rings, orbital motion + axial spin.
  3. Saturn's ring + Earth's moon + axial tilts.
  4. Asteroid belt — one InstancedMesh of ~1,800 rocks between Mars and Jupiter.
  5. Hover popup — raycast picking, the fact tooltip, hover highlight.
  6. Sun glow animation + click-to-focus camera + pause / speed controls.
  7. Polish — real facts for every body, tone mapping, responsive resize.
  8. Visual fixes (after review) — brighter lighting, decoupled Saturn ring, lit belt, counter-clockwise orbits.

Two models from the one spec: the Qwen build inlined the whole thing into a single index.html; the DeepSeek build split it into index.html + a module. Both passed the identical headless gate — the spec and the test were the constant, the model was the variable.

← Open both builds Compare: how Pac-Man went