Some checks failed
akbasic CI Build / cmake_build (push) Failing after 19s
akbasic CI Build / sanitizers (push) Failing after 13s
akbasic CI Build / coverage (push) Failing after 16s
akbasic CI Build / akgl_build (push) Failing after 18s
akbasic CI Build / mutation_test (push) Failing after 17s
The blinking backspace was not the backspace. The sink skipped rows it believed were already clear, tracked in a drawn[] array, which assumes a frame inherits the frame before it. SDL_RenderPresent swaps buffers, so a frame inherits the one two back: a row erased once is clean in one buffer and dirty in the other, and presenting alternates between them. The first character of a backspaced wrap flickered forever. It reproduces on X11 and never under the dummy driver or a software renderer, which is why the suite stayed green through two rounds of fixing it. The sink now repaints every row it owns every frame -- a frame either owns every pixel it presents or inherits pixels it cannot reason about. Confirmed on real hardware with the reported input: the wrapped tail's row reads zero across five successive captures. The cursor returns as a blinking block, half a second per cycle, off SDL's clock. It sits in the cell after the text rather than under it, which is what made the underscore unreadable, and it wraps to the next row when a line exactly fills one -- where the next character actually lands. The new regression test paints stale pixels by hand, which is what a swapped-in buffer hands back, so the case is covered without real hardware. Every new assertion was checked by reverting the fix and watching it fail. Recorded honestly in TODO.md section 5: the same buffer swap means the graphics verbs were never reliable across frames either. A one-shot DRAW lands in one buffer and the next present shows the other. Making that work needs a persistent surface, which is its own commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>