Giving the cast a face
Earfh's first generated sprites replaced its JPEG cutouts on September 17. The tooling behind them had to survive two bad measurements, one that reached a commit message and one that put two characters in every frame.
Written up later from the repo's history and dated to the days it describes.
Until September 17, the player in Earfh was a 97 by 104 pixel cutout sliced from a JPEG that had been run through a background remover. It was not pixel art and it did not sit on a pixel grid. The odd part is that the project was already configured for pixel art, with nearest filtering and pixel snapping switched on. Nobody had finished the job.
The mismatch showed up everywhere. The player's collision capsule was 12 by 24 pixels, drawn for a small sprite, under art dropped in roughly four times too large. The sprite had one animation, so walking up and walking down looked identical.
One character first
The design spec for the fix kept its scope to the player alone. The goal was to generate, slice, wire and see one character move in four directions, and to surface every pipeline question once, cheaply, before starting on the rest of the cast.
The first choice of generation style failed twice with server errors, so the sheet came from a different style that returns an animated GIF. Its 44 frames were packed into an 11 by 4 grid of 64 pixel cells. The layout was measured rather than assumed. Row 0 faced down, row 1 faced right, row 2 faced up, and row 3 was a near mirror of row 1 and went unused, because the game mirrors the side row for leftward movement. That gave six animations, idle and walk for down, up and side.
The spec also refused to resize the collider inside an art change, on the grounds that a collider changes how the game feels. The capsule grew slightly later, from the measured footprint of the finished sprite.
Two measurements that lied
The first bad measurement was about poses. Each row of the sheet looked like 11 frames and held only 4 distinct poses. The first wiring got that wrong. The walk played its last pose straight into its first at the loop seam and skipped the passing pose. On screen that is a visible foot pop.
The cause was a tool call. The measurement used Pillow's getbbox() on a difference image, and getbbox() keys off the alpha channel. Two cells that differ only in color have identical alpha, so they compare as the same. The false result reached a commit message before review caught it. Its replacement, unique_cell_map, compares raw RGBA bytes, and a regression test builds two cells with matching alpha and different colors and fails if they ever compare equal.
The second came the same evening, when Bro Magnon, Doom Scroller and Cleaner Bot got generated sheets in place of single static frames cut from JPEGs. The generator emits sheets as either 4 columns of 64 pixels or 8 columns of 32, and it does not say which. A 256 pixel wide sheet divides evenly by both, so divisibility settles nothing. Bro Magnon's sheet was the 8 column kind. Sliced at 64, it put two characters in every frame.
That passed every automated check in the pipeline. It showed up only when the result was rendered and someone looked at it. The fix, detect_frame_width, measures the spacing between figure centers instead of dividing the sheet width, and the tools README calls it the step the whole pipeline rests on.

Those first enemy sheets did not last. A remodel on September 24 replaced them with sheets drawn to one agreed layout, which is the art above. The rule outlived them. The tools README states it in bold. Render and look at the output before committing a sheet, since every check in the directory can pass on art that is wrong. The weapon spec written three days later cites the Bro Magnon case as the reason its own visual check is not optional.
The same commit also fixed two crashes that only fire during play, which Nine months of silence covers.