# Headless Godot, deterministic worldgen, and an HTTP debug surface for AI

> A Godot 4.6 / .NET 8 narrative sandbox with two parallel deterministic world grids, a headless determinism test wireable into CI, and a debug-only HTTP introspection server built specifically for AI-assisted debugging — where there is no window to eyeball.

By Jeff Mixon, published 2026-03-22. Canonical: https://www.jeffmixon.com/post/godot-debug-http-introspection-for-ai/

## The setup

A personal Godot 4.6 + C# (.NET 8) project — narrative sandbox, single
player, side-on, procedurally generated world. The gameplay loop is
deliberately small. What it is really an excuse for is figuring out how
modern engine-driven game development should change when the developer is
working alongside an AI assistant that cannot see the game window.

Two design choices fall out of that, and both ended up being independently
worth doing.

## Two parallel deterministic grids as the source of truth

The world is two `2D` arrays:

- A `TileType[,]` terrain grid (stone, soil, rope, etc.)
- A `MoleculeType[,]` atmospheric grid (O₂, CO₂, water vapor, etc.)

Both are seeded from a single world seed and reproduced bit-for-bit on
re-generation. The visual scene is a **projection** of those grids, not
their authority; if you regenerate the grids you regenerate the world.

The biome-aware procedural generation that fills the grids has one
non-negotiable property: **per-column generation depends only on
`(seed, x, layout)`**. Column at `x = 4096` is generated identically
whether or not column at `x = 4095` has been generated, whether or not
the player has visited any other column, whether or not other layers have
been generated yet. Disjoint seed offsets across layers (terrain, surface
features, sky, atmosphere) keep the layers independent.

The reason matters: with this property, the world is ready to be
*streamed* — generated lazily as the player moves — without that change
being a refactor. The mathematical guarantee is already in the
generator; the only thing missing is the cache layer that hands columns
out on demand.

It is also the property that makes the determinism *testable*.

## A headless determinism test wired into CI

Godot can run with `--headless` and a target scene. I have a scene whose
entire job is:

1. Generate the world from a fixed seed.
2. Generate it again with the same seed.
3. Hash both grids and compare.
4. `exit 0` if they match, `exit 1` if they don't.

That's it. The whole thing runs in a few seconds and is exactly the kind
of test CI is good at. The first time a refactor accidentally introduces
non-determinism — a `DateTime.Now` call, a `HashSet` iteration order, a
`Parallel.For` over uncommutative side effects — the CI step turns red.
Determinism stops being an aspiration and starts being a property of the
codebase.

## The HTTP introspection server

This is the piece I think is most likely to spread.

Modern AI-assisted programming has a blind spot: the assistant cannot see
the game running. It can read source, it can read logs, it can read a
crash dump. It cannot *look at the screen* and tell you that the player
character is one tile inside a wall. For most software this doesn't
matter; for game development it matters constantly.

So in debug builds — and only debug builds, the export filter strips it
out of releases entirely — I run a tiny HTTP server on
`127.0.0.1:9080`. It is read-only and binds only to loopback. It exposes:

- `GET /` — an index of available endpoints with descriptions.
- `GET /world` — world parameters and current seed.
- `GET /player` — player position, velocity, current state-machine state.
- `GET /tile?x=&y=` — what tile is at this cell, including its
  derivation chain.
- `GET /tree` — the live scene tree, including each node's C# type and
  the script path that defines it.
- `GET /screenshot` — a PNG render of the current viewport.

When something goes wrong, an AI assistant can — without leaving its
read-only tool surface — query the world state, look at the screen, and
form hypotheses with the same information I have when I am sitting at the
machine. The debug session shifts from "describe to the assistant what
you are seeing" to "ask the assistant to look at what you are both
seeing." Even when I am the only one in the loop, having a
machine-readable view into the running game has paid for itself
repeatedly: trivial scripting to compare states across builds, automated
screenshot regression for UI changes, scriptable repro of difficult bugs.

The contract drift problem is the obvious risk — endpoints rotting as the
gameplay code evolves underneath them. The discipline is that the
introspection server lives next to the gameplay code, not in a separate
"debug" project, and changing the contract is part of the same patch
that changes the underlying state. The same way a public API would be
treated.

## Code hygiene that ages well

A few details that aren't load-bearing for the post but are worth
stealing:

- `Godot.NET.Sdk/4.6.3`, **Roslyn analyzers raised to `Recommended`** with
  `EnforceCodeStyleInBuild=true`. Warnings are *not* treated as errors —
  prototype gameplay code shouldn't fail to build on a missing XML
  comment — but the analyzer voice is loud enough that bad patterns get
  caught early.
- Statically-typed gameplay layers (alignment-meter narrative system,
  dialogue tree, inventory, hotbar, choice dialog) built on Godot UI
  controls, with C# enums and DTOs everywhere a string could plausibly
  have lived. The C# / engine boundary is the place this matters most:
  GodotObject-vs-Node-vs-Resource is a rich enough taxonomy to confuse
  yourself with.
- **Documentation tiered three ways:** `README.md` for what is built and
  how to run it; `docs/design-vision.md` for what the project is *for*,
  with explicit "Decided" vs "Open design questions" markers; `CLAUDE.md`
  for the operational / agent guidance that has no other home. Three
  artifacts, three audiences.

## Closer

The HTTP introspection server is a small piece of code that punches above
its weight because it bridges the gap between an AI assistant's
read-only world view and the fundamentally visual nature of game
development. Determinism makes it possible to reason about that world
view at all. The two together turn "AI-assisted game development" from
an unsatisfying mismatch into a genuinely productive loop. If you are
building anything graphical and working with AI assistants, this is the
pattern I would steal first.
