The plan had three slots
screenshot.ts had grown to 626 untested lines drawing both share images and the board underneath them. The obvious three-way split needed a fourth module once someone actually drew the boundary.
The review’s sixth pick was screenshot.ts, 626 lines with no tests of its own, drawing the daily and duel share images and the board underneath both of them, board geometry and snake colors sitting in the same file as panel layout and podium rank lines. The plan going in looked clean: pull the board-drawing primitives into their own module, then a thin composer each for the daily image and the duel image, three pieces for what was clearly three concerns.
flowchart TD
accTitle: screenshot.ts refactor split into four modules
accDescr: The original 626-line screenshot.ts file containing board drawing, snake colors, share image layout, and mode-specific composers split into board.ts with drawing primitives, a shared share-image module with canvas setup and infrastructure both composers need, a daily share image composer, and a duel share image composer. The split emerged from three initially-planned pieces to four once the boundary was drawn.
subgraph before["Before: screenshot.ts (626 lines)"]
board_old["Board geometry<br/>Snake colors"]
daily_old["Daily share<br/>image layout"]
duel_old["Duel share<br/>image layout"]
shared_old["Canvas setup<br/>Fonts, palette<br/>Text truncation"]
end
subgraph after["After: Four modules"]
board["board.ts<br/>Drawing primitives"]
shared["share-image.ts<br/>Shared infrastructure"]
daily["daily-composer.ts<br/>Share image layout"]
duel["duel-composer.ts<br/>Share image layout"]
end
before -->|refactor| after
board_old --> board
shared_old --> shared
daily_old --> daily
duel_old --> duel
daily -->|reads| shared
duel -->|reads| shared
class shared accentActually drawing that boundary turned up a fourth concern the plan hadn’t named: a chunk of the file that both composers needed equally, and that wasn’t board geometry or specific to either mode. Shoving it into board.ts would have mixed drawing primitives with infrastructure that has nothing to do with geometry, and duplicating it into both composers would have recreated the exact kind of drift the split was supposed to end.
The boundary that actually shipped added a fourth module for exactly that shared infrastructure, settled through a plain conversation rather than another multi-candidate design round, since by the time the question was concrete there was really only one place each piece of code could go. screenshot.ts came apart into board-drawing primitives, a new module holding that shared share-image plumbing, and one composer each for daily and duel.
The old file was deleted outright rather than left behind as a re-export, the same call the engine split had already made a day earlier. The 433 lines of tests that used to cover the whole file split one-to-one with the four new modules, and both recap components repointed straight to their new imports with nothing standing in between.