9 July 2026
Clean, then init
The first two commits are called clean and
init, twenty-two hours apart. The repository was carved
out of a finished survivors-like — its own predecessor — and stripped
back to the parts worth keeping: a Godot 4.7 C# project, a native
UI, and the Quake session model where there is always a server and
the local player is always a client, single-player being a loopback.
The scar is still visible. The C# namespace is
SwarmNet, and the project file notes renaming it as
“a deliberate later step.” Two months later it is still
deliberate and still later.
12 July 2026
The day it became data
Three days of sand, shaders and props, and then one commit long
enough to be a patch note. Melting and freezing landed as a real
temperature model — molten wax, glass, silver, gold and steel, with
heat, melt point and freeze percentage as material properties, plus
quench and radiant-ignition reactions. Weapons moved out of code and
into weapons.json. A live Weapon Forge overlay appeared
to edit them while the game ran. Characters became sprite sheets
with optional descriptors.
Everything that mattered later is in that commit in embryo: the data
tables, the live editor next to the running game, the sim reading
the same file the tool writes. The pattern repeated for materials,
enemies, cards, biomes, lore and sounds until fourteen browser pages
were editing a live game.
25 July 2026
The world gets big
Fourteen commits in one day widened everything. Sparse per-chunk
world storage — uniform chunks plus lazy blocks on 64-bit addressing.
Lazy multi-focus baking: a bounded ring-scan around every player, so
the world never fully bakes. Every coordinate type widened for
scale.
The target it was built for: 10,240 × 6,144 cells, about
twenty-one screens across and twenty-three deep, roughly 88% caves.
A listen host holds two of those worlds — around 760 MB.
29 July – 1 August 2026
Six passes at the frame budget
A big world reveals what is slow. The performance work ran in six
documented passes, each one measured before and after rather than
guessed at. The pattern was the same every time: instrument first,
then delete.
Delete the off-screen light apron (+48% fps, +134% 1% low);
instrument the lightmap’s seed/prop/blur split that found it
The instrumentation is in the commit message alongside the fix,
because the split is what found the apron. Then the lightmap moved
to the GPU behind a CPU-fallback toggle (1.39 → 0.18 ms per run),
then terrain shading and the edge chamfer (0.73 → 0.14 ms). Then the
fallback itself was deleted:
deleted the CPU render path so terrain, lighting and decals run only
on the GPU (−996 lines), cut decal cost 1.26→0.69 ms, and set
a 300 fps target
A separate one that pays back every single launch: reimport before
every source run, gated on an mtime walk — and the insight is that
pruning .git and the build folders during the
walk takes the check from 16.4 seconds to 117 milliseconds.
1 – 3 August 2026
The pixel-grid reckoning
Three days, three bugs, all of them the same bug wearing different
clothes: two rasterised grids disagreeing about where a pixel is
when the camera sits between them. What makes this stretch worth
reading is that none of them were eyeballed. Each got a counter.
First a picket fence of blended columns walking across the screen
with the camera fraction — 7,338 of them, then 1,013, then zero on
unlit frames. Then an orange hairline on every material edge that
had a mountain behind it: 417 fringes, 3,096 pixels at 4K, now zero.
Then the real one:
5.8875 device px per world px maximised at 4K, so 13% of
world pixels drew 5 wide and the rest 6, redistributing every frame
with the camera’s sub-pixel phase and walking every material
silhouette a pixel against the parallax behind it. blended columns
fall from a 2653-count oscillation to 76.
The fix was to stop rendering the world at 1080p and drop the whole
canvas to 640 × 360. Two small tools exist purely to count
these things — one counts blended columns, one diffs jitter between
frames. They are the reason the numbers above are numbers.
3 – 17 August 2026
It becomes a game
Two weeks of systems on top of a simulation that finally ran fast
enough to carry them. Gun crafting across four platforms — rifle,
blade, shield, drone. 140 cards. Damage types, stains, triggers,
melee. A hand-written integer rigid-body solver with joints, terrain
contacts and decomposition, because float polygon physics is the one
thing that cannot survive lockstep. Trees, hanging lamps,
stalactites. Nineteen more materials. A day/night sky. Biomes.
And all the audio, which is not audio: every sound is a synth patch
rendered into memory at attach time. There are zero sound files in
the repository. The studio page that authors them previews through
the identical engine, so the preview is the bake.
18 – 27 August 2026
A hundred and thirty-two creatures
enemies: every biome has its own set now — 132 kinds each
placed from its own Noita entity, 12 movement styles traced
back to the components that justify them, and a --zoo that
stands the whole roster on one plain
A roster that size needs a way to look at all of it at once, which
is what --zoo is. Then hitboxes, animations, and
hibernation so the far ones stop thinking.
Somewhere in there is the single most specific bug in the
repository. Animation rows kept vanishing. The cause was not in the
game:
the zombie was never cropped — PowerShell’s -shl kept
the PNG header a byte, so 113×300 read as 113×44 and 15 rows
fell off; zombie 2→17, roster 961→1035
A shift operator in a build script silently truncated a third of the
animation library, and the only symptom was that creatures had fewer
poses than they were drawn with.
20 August 2026
The story closes
The narrative was not written in one sitting; it was tracked. A
folder of fourteen markdown tickets with status and blocked-by
fields, a map file recording a one-line resolution for each closed
one, and a stated destination. Ticket 01 was
“Fate of the old lore bible.” Its resolution:
discarded wholesale and the file deleted.
The last ticket closed with the line “Last ticket —
destination reached.” What came out of it: the Quiet Quarter,
the Keeping, the Kept, and the sentence the whole thing hangs on —
“keep this” arrives as “make this.”
Plus three ambiguities that are deliberately never resolved, and a
rule that no character will ever speak a line of dialogue.
31 August 2026
The fonts were never in the build
Every exported build had been wearing Godot's fallback font. Not
broken, not crashing — just quietly wrong, in a way you would only
catch by comparing an export against a source run. The raw
.ttf never entered the pack, while the UI reads it
dynamically at runtime.
The fix is one line of export config. The interesting part is the
response: a test class that pins every raw-read asset as both
keep-imported and inside an include filter, and a build script that
runs that one class before every export. The bug cannot
come back, and neither can its siblings.
7 September 2026
Tentacles, and a tower with nobody outside it
A heavy day — fifteen commits. Explosion streamers got ported
properly: seventeen presets generated from source XML, streamers
attached to twenty-one more weapon families, and a fix for beads
dashing instead of drawing a line, because trail gap now fills every
frame rather than every emission.
The same day, a mode that is just a good idea:
the tower is the arena with nobody outside it: one sealed ledged
room, the whole roster climbed weakest-first off the HP the kinds
already carry, three kills a floor, and a death that costs the
floor’s banked kills but never the floor
No new balance data — the ordering falls out of the health values
the creatures already have. And the failure state gives back
progress without giving back the climb.
8 September 2026
Two lines, and nine candidates
A whole-repository pass with an unusual thesis:
a comment says its point in two lines — the 2,420 blocks that
ran past four come down to two across the game, the tools, the
shaders and the scripts, and the generated tables are shortened at
their json and generator sources so a re-run keeps them short
The last clause is the part that makes it stick: shortening the
output of a generator is temporary; shortening the generator is
permanent.
Same day, an architecture review of nine candidates was run and then
applied — six whole, three in part. One strike seam that every blow
arrives through, one actor vocabulary, the table hash and the actor
wire codec generated from the declarations they had been drifting
away from.
13 – 14 September 2026
Reading a creature’s mind
The most recent stretch is interface work on a 960-unit canvas — the
anvil, the inventory, the material drawer, all laid out in units
two-thirds of a world pixel with text on its own finer grid — and
then a debug overlay that turned out to be a bug detector.
you can read a creature’s mind now: cl_draw_ai puts its
state, facing, footing and stuck window over its head […] out of the
sim rather than the renderer so it cannot disagree with the brain;
and two things it was built to find are already fixed — a facing of
zero, which Math.Sign hands you for prey exactly level and
which is neither side, and a dash with no cooldown, six ticks where
their reference says a hundred and twenty.
Building the window found the bugs before anyone looked through it.
And the very last commit in the log is a small, satisfying piece of
detective work: creatures were dying in their own puddles, and the
culprit was not damage at all.
the route that was actually killing them was the STAIN, not
the damage — sludge carries no hazard at all and its poison drain
bled a fume-wisp out in twelve seconds standing in its own puddle
What the shape of the log says
Across the whole history: 999,605 insertions and 398,265
deletions over 9,345 file changes. In the last thirty commits
alone, 27,903 lines added against 28,122 removed — almost exactly
balanced. That is not a project accreting features. That is a project
being rewritten in place, repeatedly, by someone who deletes as
readily as they add.
The other tell: one TODO comment exists in the entire codebase,
and it describes a hack that was retired. Gaps do not live in the code
as good intentions. They live in a todo file, there are three of them,
and one of them says of its own subsystem that it is
“two unrelated halves bolted together and neither is any
good.”