NEON CITYmaking of
04 / 07

AI agents

One human, four AI roles, zero access to production

The orchestrator plans and reviews, Claude Code takes the hard and visual tasks, Codex implements, the asset chat paints. No agent pushes, merges or deploys – a human decides after a review by a different model than the author.

4.1 Roles

The agents are not “a team that makes the game on its own”. Each has a narrow role and clearly written limits, and every decision that is hard to undo stays with a human.

  • Marcinowner

    Goals, priorities, sign-off decisions, playtests. The only one who merges into the main branch and deploys.

  • OrchestratorClaude chat

    Plans, briefs with scope and a “do not touch” list, report reviews, recommended decisions.

  • Claude Codeterminal agent

    Hard and visual tasks: rendering, look and feel, diagnosis, cross-reviews, this website.

  • Codexterminal agent

    Implementation: gameplay features, backend, arena generator, tests and reports with numbers.

  • Asset chatOpenAI image_gen

    Commissioned 2D art and 3D sheets: weapons, hands, zombie concepts, vehicles.

4.2 Rules

  1. No push, merge, deploy or secrets. Hooks in the Claude Code toolkit enforce it: they block every git push, changes on the main branch, Worker publishing, writes to R2 and reads of key files – before the command runs.
  2. Cross-review. Work is reviewed by a different model than its author, read-only; mutation tests and measurements run in copies outside the repository.
  3. At most 3 parallel sessions. Each in its own worktree, with free ports and its own report.
  4. Scope and “do not touch”. Every brief lists the files and modules outside the task. The report opens by confirming they were left alone.
  5. New features behind a flag. The existing mode must stay the baseline – down to the pixel.
  6. Look first, code second. A mock-up, sheet or concept goes for sign-off before any implementation. This site was made the same way.

BLOCKED by the Neon City hook: release without --dry-run.

Hook, on an attempt to run a publishing command (translated from Polish)

Neon City hook: test processes are still running. Stop the ones you started in this session and check again; if they belong to the owner, list them in your answer and finish.

End-of-session hook – the agent cleans up after itself and leaves other processes alone (translated)

4.3 The loop: brief → report → review → decision

Workflow diagram: Marcin sets the goal, the orchestrator writes a brief, the implementer works in its own worktree and hands in a report, a review by another model ends with REJECTED back to the implementer or ACCEPTED, then preview, staging and Marcin’s playtest, after which he merges and deploys

A brief is a short document: goal, scope, a “do not touch” list, acceptance criteria and the expected report format. The implementer works in its own worktree and finishes with a report full of numbers: tests before and after, screenshots, measurements, risks and the things it did not check.

The report goes to review. The reviewer takes nothing on trust: it rebuilds from a clean export, plants deliberate bugs to see whether the tests catch them, and looks at the screenshots. There are three possible verdicts: REJECTED, ACCEPTED WITH NOTES or ACCEPTED.

Only after acceptance does a change reach the preview and staging, where Marcin plays it. Merging and deploying is always done by a human.

4.4 Case study: TRAM-1

TRAM-1 brought trams into the ordinary match: a timetable, stops, contact with the player and the D5 warning corridor. The author’s report was long, the tests were green, and 20 arenas came out identical across two runs. The first review rejected it anyway.

  1. Review 1 · REJECTED

    Blocking: the D5 corridor was invisible from above. Its triangles had reversed vertex order and the material draws only the front face. The geometry existed, so tests and stats passed. On top of that, the tram shown in co-op drifted away from its collision, and a tram standing at a stop dealt damage.

  2. Fix 1

    Reversed winding, a test of the normal’s sign and a new smoke run counting D5 pixels in a fixed frame: 23 → 1001 pixels by day, 190 → 1212 at night. Damage only above 0.5 m/s and once per pass; at a stop: 0 HP. Prediction vs server: 0 m.

  3. Review 2 · ACCEPTED WITH NOTES

    D5, render timing and the stop were closed. Two notes: an actor pushed in front of the nose was sometimes “carried” (2–4% of trials, up to 11 m), and with 150 ms latency remote players showed up to 1.74 m inside the tram.

  4. Fix 2 · ACCEPTED

    Carried further than 1 m: 0/96 trials in Łódź and 0/96 in Kraków. Maximum overlap of remote characters with the tram: 0.055 m, 0 frames above 0.1 m. Tests: 1634 backend and 937 client, 0 failures.

Łódź from above before the fix: a tram on the street with no visible warning corridor ahead of it
review 1D5 in the shipped code – the strip is not visible. Map: © OpenStreetMap contributors (ODbL).
Łódź from above after the fix: an orange warning corridor is visible ahead of the tram
fix 1The same frame after flipping the triangles. Map: © OpenStreetMap contributors (ODbL).

The lesson: a test that checks geometry exists does not check that it can be seen. Since this fix, signing off a visual element requires measuring pixels in the frame, not just a screenshot in the report.

The author wrote it down in the fix report: the earlier images and the PASS claim did not constitute sign-off for D5. The review found a bug that none of the 1600 tests could see.

Co-op, seen from the second player’s camera: a tram with its warning corridor right next to a remote player on a street in Łódź at night
Co-op, contact with a tram – measuring how far remote characters overlap the tram body. Map: © OpenStreetMap contributors (ODbL).

4.5 Excerpts from briefs and verdicts

Short, anonymised excerpts, translated from Polish – without paths, addresses or branch names.

No game source code on the site. No push, no repository creation, no deploy. Design and mock-up for sign-off first.

Orchestrator brief – the task for this website

Every prompt comes with a scope and a “do not touch” list. New features behind a flag; the existing mode is the baseline.

Working rules shared by all briefs

No edits to shared packages, networking, the OSM parser, audio or the other agent’s directory. No amend, push or deploy.

Implementer’s report – scope confirmation at the top

Verdict: REJECTED. The author’s report lists “D5 readability” as signed off, but no screenshot shows it.

TRAM-1 review 1

The earlier D5 sign-off was wrong: the geometry existed, but the strip was not visible from above; the earlier images and PASS do not constitute sign-off.

Fix report – the author corrects its own claim

Verdict: ACCEPTED WITH NOTES. Blocking R-01 is closed, as my own pixel measurement confirms.

TRAM-1 review 2