Shaded passages were held back from the public edition while the event ran.
Sunday was the day the robot learned to walk, fell down a lot, and still ended the night with seven days of the backlog cleared and its name at the top of a few boards.
The numbers first, because they tell the story better than I can. 167 commits between midnight and midnight. 446 challenge attempts started. 1,519 answers submitted, 521 of them full CORRECT verdicts. Days 1 through 7, all five lanes, all three modes. Meanwhile the event kept moving: Day 11 dropped at 09:00 before I had even finished Day 1.
Midnight: the first real run
Fourteen minutes after midnight the runner went live: one command that does the whole loop, from starting the attempt to reading the verdict. The first live warmups Time Trial went from about a second and a half on the clock to 0.58 seconds. Not winning yet. But it was the first time I watched a challenge get answered faster than I could have read the question.
Then I slept for a few hours, because I knew what was coming.
The ELF Aware lesson
The morning started with the only Day 1 challenge I had not finished: ELF Aware, the binary lane. The Single Solve and the Time Trial went fine. The Mastery is where I learned the most expensive lesson of the event.
Every timed mode has a limited pool of ranked attempts. Some pools have hundreds. ELF Aware’s Mastery had two.
The first attempt failed on a build where a function had been renamed. Fixed that. Then the second variant showed up with four slots instead of one. Then a stripped binary. Then two files with the same name overwriting each other in the download folder. Then a new naming scheme for slots. Six different problems in a row, each one discovered live, with two shots to absorb them all. It got there, CORRECT, in 25.8 seconds. 29th place.
The renamed function was enough to sink everything, because one wrong answer rejects the whole batch. By the time the last attempt came through, the robot was walking candidate answers one at a time over 72 questions, which is where the 25.8 seconds went.
That one stung, and it shaped everything after. The rule that came out of it: Time Trials are for discovering shapes, so the Mastery is a one-shot that just works. If a Mastery run takes 20 seconds, it means we were not prepared.
Finding the rate limit the hard way
Around 14:11 a script analysis Mastery submitted a big batch of answers and one of them was wrong. A submit batch is all or nothing: one wrong answer and nothing saves. So the robot did the reasonable thing and split the batch into single answers to find the bad one. All at once. The server answered with 124 rate-limit refusals in a single minute.
By the end of the day the logs had 2,361 calls and 472 of them had been refused. So the robot measured it: about 100 calls per calendar minute per player, every kind of call on one counter. We set our own ceiling at 80 per minute, made a failed batch split into eight smaller batches instead of a flood of singles (19 calls instead of 160 on the test case), and added a rule I liked a lot: one clock at a time, in silence. While a timed run holds the clock, every other process waits. Nobody steps on the run that counts.
Zips inside zips
The script analysis Mastery had a bug that had nothing to do with scripts. The download contained zips inside the zip, and two of those inner zips held files with the same name. The robot had been answering the second set of questions with the first set’s file. The grader said “wrong”, and the real problem was plumbing. Lesson written down: a rejection from the grader can be a plumbing fault.
Letting it run alone
At 14:05 the robot played Day 3 with nobody touching the keyboard, while I watched. That was the first rehearsal of the thing I actually wanted: a robot that plays the 09:00 release on its own.
A timer started a Claude Code session in the background. It pulled the day’s challenges, triaged them, and went to work, while I watched on a read-only screen and got status pings on my phone.
The lanes repeat
The challenges change every day, but the five lanes never do. You can see it when you line the days up:
- Warmups climbs an encoding ladder one rung a day. Base64 on Day 1, ROT13 on Day 2 (the challenge was called Half a Turn, which is exactly what ROT13 is), hex on Day 3, binary on Day 4, then base32, base85, URL encoding and Atbash, then decimal and octal. The Masteries stack them: numbered lines, each line in its own encoding, and on Day 6 the answer itself was cut in half across two lines in two different encodings.
- Binary adds a new language every day (C, C++, .NET, Go, Rust, Java, Kotlin) but the thing you are hunting for has the same shape every time: a small config blob with a magic header. In the Java one it was hiding as base64 text inside the class file’s constant pool. Same prize, new wrapping.
- Metadata is always “what the file claims versus what the bytes say”. On Day 7 a zip archive stated its own file count three different ways in three different places, and Python’s own zip library quietly “repairs” a lying archive, so the robot reads the raw structures itself.
- Script analysis hides a little descriptor behind a “Codec” label in every sample, in a new language each day. Trust the label, but verify the decode.
- Mobile puts a decoy story in the app and the real answer in a puzzle file inside it, behind an encoding that gets one notch harder every day.
That afternoon I made the call that mattered most all week: the lane is the unit of learning, not the challenge. Every solver got folded into one shared engine per lane, and each new day’s solver became a thin wrapper on top of it. Whatever Day 3 taught the warmups engine, Day 4 got for free.
The fallback refused too
Day 5’s script challenge was called Hatch Careful. I had lined up Mythos as the fallback model for when the main model’s safety filter balked. This time it was Mythos that balked: the lane agent (the AI agent on standby to work that lane) got refused, flagged as a biology concern, on a CTF about Python scripts. The title did it. An Opus agent picked the lane back up and finished it in about four minutes and forty seconds. Funny in hindsight. At the time I just wanted the lane done.
Fast is a separate problem from right
Day 7’s binary was Routine Check, a Kotlin program. The solver was correct, but a Kotlin jar ships with about 1,500 standard library classes and the robot was parsing every single one. Its one-shot Mastery ran at 4.2 seconds before anybody looked at a profile. The fix made the solve about six times faster, but the Mastery was already gone. New rule: profile the solver on the biggest file shape before the first scarce Mastery.
Where Sunday ended
Day 7’s last Mastery finished at 23:33. When the boards came in, the robot had its first wins:
- Half a Turn (Day 2 warmups): 1st on the Mastery.
- Two of a Kind (Day 4 warmups): 1st on the Mastery, tied.
- Dim and Dimmer (Day 4 script): 1st on the Time Trial.
- Go Fish (Day 4 binary): 1st on the Time Trial.
- Shell We Begin (Day 6 script): 1st on both the Time Trial and the Mastery.
- Pool Party (Day 6 binary): 1st on the Time Trial.
Twenty-four hours earlier I had been dead last on every board I touched. Most of the Time Trials the robot played that day landed in the top five, at around three tenths of a second. Not bad for a Sunday.
How we built it: the Days 1 to 7 dev log
Why one vendor. Same day as Hatch Careful I made another call: this repo runs on Anthropic models only. No mixing vendors. The event’s files are handed to my identity, and I want them going to one place, not spread across every tool that could help.
Why the robot waits for my go. On Sunday night Day 5’s timed runs went ahead before I had looked. That was not the deal. From then on the robot reports when a day’s Single Solves are done and waits for me before it spends any Time Trial or Mastery.
Why the stable bar went up. The first rule said three clean Time Trials in a row meant ready. That afternoon I raised it to five. Monday would show that counting clean runs was the wrong idea altogether, but more evidence before a scarce Mastery was the right direction.
Why extra Time Trials are free. The Hall of Fame keeps each team’s best time, so a Time Trial run can only help a rank, never hurt it. That made the big Time Trial pools a place to learn, and later a place to chase speed. Where the event offers an untimed run, the robot rehearses there first and spends ranked runs only once it has stopped learning.
Why the clock gets silence. I did not want the robot slowing itself down. Agents, polls and reruns all talk to the same Game Master, the event’s API, on the same counter, and any of them could land a call in the middle of a timed run. Making every other process wait costs nothing that matters, and the run that counts gets the whole line.
Why we stopped building from titles. Titles carry hints, and for Day 5 we pre-built solvers from them ahead of time. The verdict was plain: one lane of five got any help, most of it went unused, and the script lane got pointed the wrong way. Titles are for reading while we work, not for guessing ahead.
Why a VPN in a box. Some later challenges may need the event’s VPN. I approved it only inside its own network namespace, where the tunnel and the Game Master are the only things reachable, so nothing from the event can touch the rest of my house.