Launching Age of Poleis to check a small detail. Did I successfully convey during onboarding the meaning to continue exploration or not. And here I am already exploring the entire island in search of the artifact needed to start. Strange feeling. I designed the game. I know which buildings will unlock next, where the economy will start to squeak and where everything is heading. I have more spoilers than anyone else. And yet, sometimes I close the checklist and continue building the city—just because I want to.
Age of Poleis is a strategy game about ancient Greek city-states. Building, resources, workers, and production are interconnected here: change one mechanic—and three others will follow. The code is written by AI, and I am the one who comes up with, solves, and plays.
Below is how I set up the process to let the agent work almost without me, and two cases from a real project. The first is about a rule I was tired of repeating. The second is about thirty green tests that proved nothing.
If you explain it a second time—it's already a rule
Backend on Django, interface on React and TypeScript, with API in between. Contracts are described on the backend, from which an OpenAPI schema is generated, and from the schema TypeScript types are created.
Django → OpenAPI → TypeScript types → interface code
The trap here is obvious. The type on the frontend doesn't match what came from the API, and it's very tempting to just fix it manually: one line, a minute of work. But when the next generation happens, the fix quietly disappears, and the bug returns.
When I caught myself explaining this in chat not for the first time, the rule moved into the agent's permanent instructions. Generated files should not be touched manually. If the contract changes—change the source and regenerate. A re-run of generation should not change anything.
- Fix root causes; do not silence failures with skipped tests, broad assertions, duplicated
flows, generated-file edits, or an alternate database.
- API-owned TypeScript types come from generated OpenAPI. Client-owned types remain local.
- API boundary: backend source change, OpenAPI/type regeneration, frontend validation.
But the rule in the text is still a wish. Therefore, in the general project check script, there is a step that generates the schema and types into temporary files and compares them with what is in the repository. If they differ, the check is red.
def run_frontend_contract(gate: Gate, temporary: Path, generated_types: Path) -> None: if gate.run( "Generate TypeScript API types into an isolated file", [NPM, "exec", "--", "openapi-typescript", str(OPENAPI), "-o", str(generated_types)], cwd=FRONTEND, ): gate.check( "TypeScript API types drift", lambda: assert_same( "frontend/src/types/generated/api.ts", generated_types, GENERATED_TYPES ), )Since then, I have a simple schema: the rule, the way to perform it, and the check. Without the check, the rule is followed as long as the agent remembers it. With the check, it is always enforced. It also closes formatting, localization, and any other routine that repeats.
Thirty green tests that checked the wrong thing
Windows version launched like this: first a small loading window, then a separate game window. On exit, another waiting window. It worked, but it looked like three different programs. I wanted it to be human-like: one window, with loading, then the game. Closing it made the window disappear.
The task is on one line in words. In code, there are several states: startup, loading, closing during startup, saving, and restarting.
The most interesting thing happened even before the first line of code. All 30 existing tests for the shell and window management were green. And that makes sense: they checked the old behavior—the very one I wanted to get rid of. Green meant "works as before," but I needed "works differently."
Therefore, the first thing was to create a new window lifecycle test. On the old code, it failed: it looked for the main window but found the loading window. After the refactoring, it passed. Now I can say the task is solved, not just that "nothing broke."
To let the agent check this by itself, I translate the wish into something visible:
loading and game run in one window;
closing during startup does not open a new window;
the saved campaign remains in place after restart.
In the end, 96 JavaScript shell tests passed, and the agent ran the real Electron application separately. One window from loading to game, closing without extra windows, the campaign alive after restart. Manual saving survived closing with the same identifier, name, and game moment.
And another line I now require in every report: what wasn't tested. Here it's a clean Windows installation, which is a separate task. A month later, such a line saves from false confidence.
In the same task, there was a good example of why simply getting a screenshot from an agent is not enough. The first frame, which was supposed to confirm entry into the campaign, still showed the preparation menu. There was an image, but no evidence of the game launch. Confirmation came only from a later frame of the campaign itself along with checking the actual application window. Now, the rules separately state: successful creation of a screenshot does not yet prove that the required state is on it.
My job is to play
When the technical part is checked without me, I start the game with different questions. Not "does the button work," but "do I want to press it."
The mechanics may be technically flawless but still boring. A new feature can sometimes just add another click. A more complex economy easily turns into accounting. And no test will catch this.
Therefore, while playing, I keep track of myself: where I lost focus, where I tried to speed up time, where I first thought about the gameplay. The moment when I forgot about the test and just played, I analyze separately. What exactly pulled me in is what needs to be strengthened.
There was a moment when I realized that selecting the next resident for the next required profession at the beginning was fun, but after 100 game periods it had already become tiring. The result was automatic candidate selection based on criteria; now I simply act as a manager, giving orders and directing learning.

For honesty's sake: what I like doesn't say anything about other players. For that, we need other players' progress. But if the author doesn't feel like leaving their game, that's a good sign.
Perfectionism vs. Randomness
I also have a completely personal problem, which causes the production to stretch out a lot. Perfectionism.
I see a button that is slightly uneven in the dialog window. A panel shifted a little. Event text that isn't entirely clear on how the mechanics work and where they will trigger again. And that's it: I jump in to fix it. Then I start the game over again to go through the entire path once more.

This way I replay the game dozens of times. And for a couple of months, I'm mostly fixing things that irritate the eye, not the things that are actually important.
And every time I hit the same wall. No matter how much I polish the perfect start, the randomness I've built into the game makes each playthrough different — from the beginning and onwards, at every stage. You can't perfect the playthrough completely: the next playthrough will still go its own way.
It's kind of funny. Replay is the main brake on my production. And it's also the best way to show that the game is alive: even I don't know in advance how the next playthrough will turn out.
What AI Can't Do for Me
Packaging, labeling, certification, platform requirements — each of these tasks has its own process and ways to ensure everything is in order. AI helps here too, but that's a separate story.
Marketing is even more complicated. Sketching a description with AI takes five minutes. Understanding who needs this game, what to show first, and how to explain it to someone who's hearing about it for the first time — that's already not possible. The game plus a pack of posts isn't the audience yet.
So my work is slowly spreading out: game design, project structure, rules for the agent, release, conversations with future players. The time for this has emerged precisely because technical tasks are going through a full cycle — from code to testing and fixing — without me.
And now I'll go launch the game. Just check one small detail.
The free demo can be downloaded here.