Building Gearwind
A lost SNES Zelda about floating islands, built by agents that argue with each other
The brief
I asked for a top-down action-adventure at the quality of A Link to the Past. Steampunk, floating islands, vanilla JS and canvas, no engine and no libraries. The part that mattered was how it got built: split the work into pieces small enough to judge on their own, and for each piece run a builder agent and a separate critic agent with fresh context. The critic had to look at the real running output, pull up actual SNES screenshots, compare them blind, and ask whether ours could pass as a lost cartridge. If not, name the single biggest gap and send it back.
Then loop until it wins.
I gave it a live progress page and left it running. It went twenty-nine rounds, 227 agents, and about 36 million tokens of sub-agent work before every piece passed.
Hard constraints do most of the work
256×224 internal resolution, 16×16 tiles, integer scaling, 15 colours per sprite, no alpha blending, no gradients. Those rules came from the SNES itself, and having them written down meant the agents could check each other against something real instead of against taste.
The critics kept contradicting each other
The loop stalled early. One critic failed the terrain for reading like a modern indie game, saying the grass was too saturated and too busy. The builder flattened it. The next critic failed the same tileset for being flat single-colour green, which is the exact failure the spec warned about. Two rounds burned, and the piece ended up back where it started.
Both critics were describing a feeling. Neither had anything to point at.
So I stopped the argument and measured the reference instead. I wrote a script that downsamples the real screenshots back to native resolution and counts what is actually there: how many pixels in a 16×16 tile differ from the base colour, how many distinct colours a block uses, how many colours are on screen at once.
ALttP's overworld grass is #489848. It is bright and fairly saturated, not the muted olive one critic had demanded. A terrain tile carries around 61 non-base pixels out of 256, roughly a quarter of its area, drawn from three to five colours. A whole screen shows 40 to 90 distinct colours.
Those numbers went into a file the agents read, plus a second script that scores our own screenshots the same way. After that, critics were not allowed to fail a piece on a claim the measurement contradicted. Two of them were formally overturned for trying.
The rule that made it converge
Once critics had to measure, they started overturning themselves. One later wrote out five objections it had planned to raise, then killed all five after checking them against the reference, and recorded them in its verdict "so nobody re-litigates them."
The same bug, eleven times
Every piece passed on its own and the game was still wrong. The pattern repeated for most of the build: a module gets written, gets reviewed, passes, and then nothing calls it properly.
The sound bank shipped 33 authored effects and combat called none of them, so a connecting sword swing made no noise at all. The player's death animation was drawn, approved, and read zero times during an actual death. Enemies never received the player's position, so the clockwork beetle's aiming code had never once run in the shipping game. Knockback was stored as [0, 0] with a live timer, so struck enemies flashed nothing and moved nowhere. The dungeon had no drops and no pots, which made dying the cheapest way to heal.
None of these show up in a diff. They only show up if you drive the running game and measure what happened.
The fix was to give a whole round over to call sites, and to tell every critic to instrument the thing and count. A critic checking the death animation patched the sprite lookup, killed the player with real damage, and reported the read count: zero before, 122 after, in both halves of the game.
Reviewing the diff is not reviewing the game
Every one of these bugs sat in code that looked correct. The question that caught them was never "does this read right" but "how many times did it fire, and what were the numbers."
A critic caught its own probe lying
The critics wrote about 500 throwaway scripts to answer their own questions. Does the beetle aim at the player. How far does an enemy actually recoil once you subtract its patrol. How many frames is the landed pose visible before the letterbox covers it.
That habit paid off in a way I did not expect: several of them found bugs in their own measurements before reporting.
One measured combat sounds as 3 dB quieter than the builder claimed. Instead of filing a regression it traced the gap, found it had tapped the music bus before the stereo panner while the effects were tapped after, and that a centre pan costs 3.01 dB. It fixed its own script and then confirmed the builder's numbers to within a tenth of a decibel.
Another found that a helper every probe depended on was reading kb.x and kb.y from an object whose fields are vx and vy. That helper printed a zero knockback vector no matter what the real one was. Any future critic re-running the old script would have "confirmed" a bug that had already been fixed and measured.
Stale probes need a written record
Three separate probes went stale during the build, each one reporting a failure that was not real. I kept a list of them in the handoff notes so a fresh agent would check the tool before believing the result.
Running out of tokens at bedtime
Around 10pm I realised I would hit my usage limit before the build finished, and the limit reset at midnight. I wanted to go to bed and have it keep working.
A cloud schedule was the obvious answer and it does not work here, because the project only exists on my laptop with no git remote for a cloud agent to check out. So the loop stayed local: an hourly job from midnight to 8am, plus a handoff document written for an agent with no memory of any of this.
The handoff turned out to be the important part. It records the method, the tooling, the current state of every piece, and one section I would not have thought to write: how to recover a workflow that died. Agents get killed by session limits mid-round, and their completed verdicts survive in a journal file. Parsing that file back out saved a full round of critique twice.
The limit hit at 6:30pm and again overnight, killing fourteen agents across three rounds. Nothing was lost. The next firing read the journals, recovered every verdict, and relaunched only the lanes that had failed.
Write the handoff before you need it
The most useful line in mine explains why the loop converges: critics measure instead of arguing, and may not raise an objection that contradicts a measurement. A fresh agent would have dropped that rule and the flip-flopping would have started again.
Whether it is any fun
Passing a screenshot test is not the same as being worth playing, so the last round put five critics through the whole chapter with different jobs: a first-time player, someone judging combat feel, someone timing the pacing, someone doing the blind authenticity test, and one whose only task was to break it.
The breaker earned its keep. It found that the ladder out of the dungeon printed "Marla is waiting at the top" and then put you back in the room you came from, which stranded the entire cog economy behind a door that only opened downward.
The pacing critic caught something better. Two earlier testers had reported the boss dying on the first attempt every time, and a third called it a wall. The lead resolved the contradiction by reading the bot's script: the autopilot's own code contained the answer to the fight. Nothing in the game told a human that compressed air opens the boiler's valve. Bots killed it instantly, humans reached attempt eleven.
The fix was a brass plaque on the wall and a line when the doors slam. Afterwards a bot that reads the room and knows nothing else kills the boss in a median of two attempts, and it connects with the solve earlier than the bot that was told the answer.
The verdict came back: fun, holds together, and it would pass as a lost SNES Zelda to anyone not staring at the status bar. One tester's favourite moment was the tin soldier that rings off your blade from the front and takes damage from behind, teaching the whole grammar of the second half without a line of text.